home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
v10n19.arc
/
PATCH.ARC
/
PATCH.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-10-24
|
150KB
|
4,676 lines
;--------------------------------------------------------------------;
; PATCH * Michael J. Mefford ;
; ;
; Program customizer ;
;--------------------------------------------------------------------;
_TEXT SEGMENT PUBLIC 'CODE'
ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT,SS:_TEXT
ORG 100H
START: JMP MAIN
; DATA AREA
; ---------
COLOR_ATTRIBS STRUC
B DB 71H ;Blue on lt. gray ;Menu
W DB 17H ;Lt. gray on blue ;Inactive window
C DB 31H ;Blue on cyan ;Active bar
I DB 1FH ;White on blue ;Active window
A DB 07H ;Lt. gray on black ;Inactive bar
S DB 10H ;Black on blue ;Unavailable entry
T DB 01H ;Blue on black ;Unavailable bar
COLOR_ATTRIBS ENDS
COLOR COLOR_ATTRIBS <>
COLOR_ATTR COLOR_ATTRIBS <>
MONO_ATTR COLOR_ATTRIBS <70H, 07H, 70H, 0FH, 70H, 00H, 00H>
BORDER_FLAG DB 0 ; =1 to disable.
XMODEM_FLAG DB FALSE ; =1 to disable file size check.
COPYRIGHT DB "PATCH 1.0 Copyright (c) 1991 Michael J. Mefford",CR,LF
FIRST_RIGHTS DB "First Published in PC Magazine, November 12, 1991",CR,LF,LF
SYNTAX LABEL BYTE
DB "Syntax: PATCH [.ZIF directory] [program directory]",CR,LF,LF
DB "$"
TAB EQU 9
CR EQU 13
LF EQU 10
CTRL_Z EQU 26
SPACE EQU 32
BOX EQU 254
FF EQU 12
SINGLE_QUOTES EQU 44
DOUBLE_QUOTES EQU 34
SHIFT_KEYS EQU 00000011B
RIGHT_SHIFT EQU 00000001B
LEFT_SHIFT EQU 00000010B
CTRL_KEY EQU 00000100B
ALT_KEY EQU 00001000B
ESC_SCAN EQU 01H
Y_SCAN EQU 15H
N_SCAN EQU 31H
F1_SCAN EQU 3BH
F2_SCAN EQU 3CH
F3_SCAN EQU 3DH
F4_SCAN EQU 3EH
F5_SCAN EQU 3FH
F6_SCAN EQU 40H
F7_SCAN EQU 41H
F8_SCAN EQU 42H
F9_SCAN EQU 43H
F10_SCAN EQU 44H
KB_FLAG EQU 17H
UP_SCAN EQU 48H
DOWN_SCAN EQU 50H
LEFT_SCAN EQU 4BH
RIGHT_SCAN EQU 4DH
PGUP_SCAN EQU 49H
PGDN_SCAN EQU 51H
BS_SCAN EQU 0EH
DEL_SCAN EQU 53H
HOME_SCAN EQU 47H
END_SCAN EQU 4FH
ENTER_SCAN EQU 1CH
TAB_SCAN EQU 0FH
CTRL_HOME_SCAN EQU 77H
CTRL_END_SCAN EQU 75H
PLUS1_SCAN EQU 0DH
PLUS2_SCAN EQU 4EH
MINUS1_SCAN EQU 0CH
MINUS2_SCAN EQU 4AH
SHIFT_F4 EQU 57H
SHIFT_F5 EQU 58H
SHIFT_F6 EQU 59H
SHIFT_F9 EQU 5CH
SHIFT_F10 EQU 5DH
CTRL_F2 EQU 5FH
ALT_F1 EQU 68H
SPACE_SCAN EQU 39H
LEFT_ARROW EQU 27
RIGHT_ARROW EQU 26
UP_ARROW EQU 24
DOWN_ARROW EQU 25
COMMA EQU ","
DECIMAL_POINT EQU "."
PLUS_SIGN EQU "+"
MINUS_SIGN EQU "-"
NOTE EQU 1046 ; C
PORT_A EQU 60H
TRUE EQU 1
FALSE EQU 0
FILE_CURRENT DB FALSE
LISTING_TYPE EQU 0
FILE_TYPE EQU 1
CUSTOM_TYPE EQU 2
SELECT_TYPE EQU 3
STATE DB LISTING_TYPE
DOS_VERSION DW ?
SCREEN_COLOR DB ?
BREAK DB ?
DEFAULT_DRIVE DB ?
CURRENT_DIR DB 66 DUP (?)
ZIF_DRIVE DB ?
ZIF_DIR DB 66 DUP (?)
SPEC_SIZE EQU $ - ZIF_DRIVE
PGM_DRIVE DB ?
PGM_DIR DB 66 DUP (?)
MATCHING STRUC
RESERVED DB 21 DUP (?)
ATTRIBUTE DB ?
FILE_TIME DW ?
FILE_DATE DW ?
SIZE_LOW DW ?
SIZE_HIGH DW ?
FILE_NAME DB 13 DUP (?)
MATCHING ENDS
FILE_RECORD STRUC
LIST_NAME DB 12 DUP (?)
FILE_RECORD ENDS
KILOBYTES = 1024
PARAGRAPH = 16
FILENAME_SIZE = 64 ;64K
ZIF_BUFF_SIZE = 64 ;64K
PGM_BUFF_SIZE = 64 ;64K
BAC_BUFF_SIZE = 64 ;64K
FILENAME_SEG DW ?
ZIF_BUFF_SEG DW ?
PGM_BUFF_SEG DW ?
BAC_BUFF_SEG DW ?
BUFFER_SIZES EQU (FILENAME_SIZE+ZIF_BUFF_SIZE+PGM_BUFF_SIZE+BAC_BUFF_SIZE) * (KILOBYTES/PARAGRAPH)
TEMP_RECORD EQU FILENAME_SIZE * KILOBYTES - SIZE FILE_RECORD
DTA DB SIZE MATCHING DUP (?)
ASCIIZ_NAME DB 13 DUP (?) ;ASCIIZ name.
BACKUP_NAME DB 13 DUP (?)
FAIL_FLAG DB FALSE ;True if open failed.
ROW DW 0
CRT_MODE EQU 49H
CRT_COLS EQU 4AH
CRT_ROWS EQU 84H
COLUMNS DW ?
CRT_WIDTH DW ?
CRT_START DW ?
STATUS_REG DW 3BAH
VIDEO_SEG DW 0B000H
ROWS DB 24
LISTING_TOP EQU 5
MENU_LINES EQU 6
CUSTOM_START EQU (SIZE FILE_RECORD + 1) * 2
COLOR_TOP EQU LISTING_TOP
SELECT_START EQU CUSTOM_START + ((CAT_NUL - CAT_TEXT + 2) * 2)
HOT_TOP EQU LISTING_TOP + 1
COM_TOP EQU LISTING_TOP + 2
LPT_TOP EQU LISTING_TOP + 3
TEXT_TOP EQU LISTING_TOP + 4
NUMBER_TOP EQU LISTING_TOP + 5
PICK_TOP EQU LISTING_TOP + 6
WINDOW_TOP EQU 24 / 2
LISTING_LEN DW ?
LISTING_ADDR DW 0
BAR_ADDR DW 0
LAST_ADDR DW ?
FILENAME DW ? ;Address of filespec to parse.
ZIF_BYTES DW ?
PGM_BYTES DW ?
FILE_CNT DW 0
MODIFY_FLAG DB FALSE
LISTING_MENU LABEL BYTE
DB "Select Utility then press Enter to select custom category. Esc to Exit",0
CUSTOM_MENU LABEL BYTE
DB "Select custom category then press Enter to customize. Esc to Exit",0
STAR_DOT_ZIF DB "*"
ZIF_EXT DB ".ZIF",0
ZIF_LEN EQU $ - ZIF_EXT
NONE_FOUND DB "No .ZIF files were found",CR,LF,LF,"$"
NOT_ENOUGH DB "Not enough memory",CR,LF,LF,"$"
CRLFLF DB CR,LF,LF,"$"
; CODE AREA
; ---------
KBD_STATUS DB ?
INT_9 PROC NEAR
PUSH AX
IN AL,PORT_A
CMP AL,0E0H
JZ INT_9_END
CMP AL,0E1H
JZ INT_9_END
MOV CS:KBD_STATUS,AL
INT_9_END: POP AX
JMP DWORD PTR CS:OLD9
INT_9 ENDP
;----------------------------------------------;
INT_24 PROC NEAR
STI
PUSHF
MOV CS:FAIL_FLAG,TRUE
MOV AL,3
CMP CS:DOS_VERSION,300H
JAE INT_24_END
XOR AL,AL
INT_24_END: POPF
IRET
INT_24 ENDP
;----------------------------------------------;
MAIN PROC NEAR
CLD
MOV AH,30H
INT 21H
XCHG AL,AH
MOV DOS_VERSION,AX
CALL INSTALL_9
CALL INSTALL_24
XOR BH,BH
MOV AH,8
INT 10H
MOV SCREEN_COLOR,AH
MOV AX,3300H ;Get Ctrl-Break state.
INT 21H
MOV BREAK,DL
XOR DL,DL
MOV AX,3301H
INT 21H
MOV AH,19H ;Get default drive so can
INT 21H ; restore after we change it.
MOV DEFAULT_DRIVE,AL
MOV BX,OFFSET STACK_POINTER + 15
MOV CL,4
SHR BX,CL
ADD BX,BUFFER_SIZES
MOV AH,4AH ;Allocate memory.
INT 21H
JNC SETUP_STACK
MOV DX,OFFSET NOT_ENOUGH
JMP ERROR_EXIT ;If not enough, exit.
SETUP_STACK: MOV AX,OFFSET STACK_POINTER
MOV SP,AX ;Set up stack.
ADD AX,15
MOV CL,4
SHR AX,CL
MOV CX,DS
ADD AX,CX
MOV FILENAME_SEG,AX ;And data segments.
ADD AX,FILENAME_SIZE * (KILOBYTES / PARAGRAPH)
MOV ZIF_BUFF_SEG,AX
ADD AX,ZIF_BUFF_SIZE * (KILOBYTES / PARAGRAPH)
MOV PGM_BUFF_SEG,AX
ADD AX,BAC_BUFF_SIZE * (KILOBYTES / PARAGRAPH)
MOV BAC_BUFF_SEG,AX
MOV DX,OFFSET DTA
MOV AH,1AH
INT 21H
CALL PARSE
CALL FIND_FILES
MOV DX,OFFSET NONE_FOUND
CMP FILE_CNT,0
JZ ERROR_EXIT
CALL VIDEO_SETUP
CALL HIDE_CURSOR
CALL DISP_DIR
MOV SI,OFFSET LISTING_MENU
CALL DISPLAY_MENU
CALL DISP_LISTING
CALL DISP_FILE
JMP SHORT NEXT_KEY
;************* Main Loop *************;
NEXT_KEY: CALL GETKEY
JC GOOD_EXIT
CMP AL,RIGHT_SCAN
JZ ENTER1
CMP AH,CR
JNZ CK_SPACE
ENTER1: CALL FILE
MOV STATE,LISTING_TYPE
CALL DISP_LISTING
CALL DISP_FILE
MOV SI,OFFSET LISTING_MENU
CALL DISPLAY_MENU
JMP NEXT_KEY
CK_SPACE: CMP AH,SPACE
JBE MAIN_DISPATCH
CALL SEARCH
JMP NEXT_KEY
MAIN_DISPATCH: MOV DI,OFFSET L_DISPATCH
MOV CX,L_LEN
CALL DISPATCH
CALL DISP_LISTING
JMP NEXT_KEY
;----------------------------------------------;
ERROR_EXIT: CALL PRINT_STRING
MOV AL,1
JMP SHORT EXIT
GOOD_EXIT: CALL CLOSE_SCREEN
XOR AL,AL ;EL=0.
EXIT: PUSH AX
CALL UNINSTALL_9
CALL RESTORE_DIR
MOV DL,BREAK
MOV AX,3301H
INT 21H
TERMINATE: MOV DX,OFFSET COPYRIGHT
CALL PRINT_STRING
POP AX
MOV AH,4CH
INT 21H
MAIN ENDP
;**************
; SUBROUTINES *
;**************
BACKUP_FLAG DB ? ;=TRUE if backup made.
FILE: MOV BACKUP_FLAG,FALSE
CMP FILE_CURRENT,TRUE
JZ DO_FILE2
JMP FILE_END
DO_FILE2: CALL SET_PGM
CALL MAKE_FILENAME
DO_FILE3: MOV DX,OFFSET ASCIIZ_NAME
XOR CX,CX
MOV AH,4EH
INT 21H
JNC READ_FILE
CALL NEW_PGM
JNC DO_FILE3
JMP FILE_END
READ_FILE: CALL READ_PGM
JNC CK_SIZE
JMP FILE_ERR
CK_SIZE: MOV AX,DTA.SIZE_LOW
MOV CX,DTA.SIZE_HIGH
MOV BX,FILE_SIZE[0]
CMP AX,BX
JNZ CK_MODEM
CMP CX,FILE_SIZE[2]
JZ DO_FILE
CK_MODEM: CMP XMODEM_FLAG,TRUE
JZ DO_FILE
ADD BX,7FH ;128-1
AND BX,NOT 7FH ;Round up.
CMP AX,BX
JNZ WRONG_SIZE
MOV SI,FILE_SIZE
PUSH DS
MOV DS,PGM_BUFF_SEG
CMP BYTE PTR [SI],0
POP DS
JNZ WRONG_SIZE
XMODEM: CALL DO_XMODEM
JC FILE_END
DO_FILE: MOV STATE,FILE_TYPE
CALL DISP_LISTING
NEXT_FILE: MOV SI,OFFSET CUSTOM_MENU
CALL DISPLAY_MENU
CALL DISP_FILE
NEXT_FILE2: CALL GETKEY
JC FILE_END
CMP AL,LEFT_SCAN
JZ FILE_END
MOV BX,CUSTOM_ADDR
CMP AH,CR
JZ DO_MENU2
CMP AL,RIGHT_SCAN
JZ DO_MENU2
CMP AL,UP_SCAN
JNZ CK_DOWN
CMP BX,OFFSET CATEGORY + SIZE CAT
JZ NEXT_FILE2
SUB CUSTOM_ADDR,SIZE CAT
JMP NEXT_FILE
CK_DOWN: CMP AL,DOWN_SCAN
JNZ NEXT_FILE2
ADD BX,SIZE CAT
CMP BX,OFFSET CAT_END
JAE NEXT_FILE2
MOV CUSTOM_ADDR,BX
JMP NEXT_FILE
DO_MENU2: CMP [BX.CAT_STATUS],INACTIVE
JZ NEXT_FILE2
MOV STATE,CUSTOM_TYPE
PUSH BX
CALL DISP_FILE
POP BX
CALL [BX.CAT_MENU]
JMP DO_FILE
WRONG_SIZE: CALL DO_WRONG
JMP FILE_END
FILE_ERR: CALL BEEP
FILE_END: CALL SET_ZIF
RET
;----------------------------------------------;
CANT_FIND LABEL BYTE
DB "╔═════════════════════════════════════════╗",0
PATH_EDIT_LEN EQU $ - CANT_FIND - 5
DB "║ Can't find ",0
CANT_FIND2 LABEL BYTE
DB " Enter new path ║",0
DB "║ ║",0
DB "║ Esc to Cancel ║",0
DB "╚═════════════════════════════════════════╝",0
NEW_PGM: CALL BEEP
CALL RESTORE_DIR
CALL CALC_WINDOW
ADD BP,SELECT_START
MOV DI,BP
MOV SI,OFFSET CANT_FIND
MOV BH,COLOR.W
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV DI,BP
CALL WRITE_STRING
CALL WRITE_NAME
MOV SI,OFFSET CANT_FIND2
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV DI,BP
MOV ADDR_SCREEN,DI
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV DI,BP
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV DI,BP
CALL WRITE_STRING
MOV CX,PATH_EDIT_LEN - 2
MOV SI,OFFSET PGM_DRIVE
MOV DI,OFFSET DTA
LODSB
ADD AL,"A"
STOSB
MOV AL,":"
STOSB
NEXT_PATH: LODSB
OR AL,AL
JZ NEW_PATH2
STOSB
LOOP NEXT_PATH
NEW_PATH2: JCXZ NEW_PATH3
MOV AL,SPACE
REP STOSB
NEW_PATH3: XOR AL,AL
STOSB
MOV LINE_START,OFFSET DTA
MOV LINE_END,OFFSET DTA + PATH_EDIT_LEN
MOV AX,ADDR_SCREEN
ADD AX,2 * 2
MOV SCREEN_START,AX
MOV LEGAL_CHARS,OFFSET ALL_CHARS
CALL EDITOR
JC NEW_PGM_END
MOV SI,OFFSET DTA
MOV DI,OFFSET PGM_DRIVE
CALL PARSE_IT
CALL DISP_DIR
CLC
NEW_PGM_END: RET
;----------------------------------------------;
SIZE_MSG LABEL BYTE
DB "╔════════════════════════════════════════════════════════════════╗",0
DB "║ ",0
SIZE_MSG2 LABEL BYTE
DB " size does not match the SIZE in the .ZIF file. ║",0
XMODEM_MSG LABEL BYTE
DB "║ ║",0
DB "║ However, ",0
XMODEM_MSG2 LABEL BYTE
DB " appears to have been downloaded via the ║",0
DB "║ XMODEM protocol which rounds a file up to a 128 byte multiple. ║",0
DB "║ ║",0
DB "║ If you have backed-up ",0
XMODEM_MSG3 LABEL BYTE
DB " it's Okay to continue. ║",0
DB "║ Continue Y/N? ║",0
DB "╚════════════════════════════════════════════════════════════════╝",0
WRONG_MSG LABEL BYTE
DB "║ It's suggest that you download from ZiffNet the latest version ║",0
DB "║ of ",0
WRONG_MSG2 LABEL BYTE
DB " Press any key ║",0
DB "╚════════════════════════════════════════════════════════════════╝",0
DO_XMODEM: CALL BEEP
CALL DISP_SIZE
MOV SI,OFFSET XMODEM_MSG
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV DI,BP
CALL WRITE_STRING
CALL WRITE_NAME
MOV SI,OFFSET XMODEM_MSG2
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV DI,BP
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV DI,BP
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV DI,BP
CALL WRITE_STRING
CALL WRITE_NAME
MOV SI,OFFSET XMODEM_MSG3
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV DI,BP
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV DI,BP
CALL WRITE_STRING
CALL GETKEY
CMP AL,Y_SCAN
CLC
JZ XMODEM_END
STC
XMODEM_END: RET
;----------------------------------------------;
DO_WRONG: CALL BEEP
CALL DISP_SIZE
MOV SI,OFFSET WRONG_MSG
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV DI,BP
CALL WRITE_STRING
CALL WRITE_NAME
MOV SI,OFFSET WRONG_MSG2
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV DI,BP
CALL WRITE_STRING
CALL GETKEY
RET
;----------------------------------------------;
DISP_SIZE: CALL CALC_WINDOW
ADD BP,CUSTOM_START
MOV DI,BP
MOV SI,OFFSET SIZE_MSG
MOV BH,COLOR.W
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV DI,BP
CALL WRITE_STRING
CALL WRITE_NAME
MOV SI,OFFSET SIZE_MSG2
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV DI,BP
RET
;----------------------------------------------;
WRITE_NAME: MOV CX,12
MOV SI,OFFSET ASCIIZ_NAME
CALL WRITE_LINE
CALL PAD_LINE
RET
;----------------------------------------------;
CALC_WINDOW: MOV AX,WINDOW_TOP
CALL CALC_ADDR
MOV BP,DI
RET
;----------------------------------------------;
SEARCH: PUSH DS
CMP AH,"a"
JB DO_SEARCH
CMP AH,"z"
JA DO_SEARCH
AND AH,5FH
DO_SEARCH: MOV SI,BAR_ADDR
MOV DS,FILENAME_SEG
CMP [SI],AH
JZ NEXT_SEARCH
XOR SI,SI
JMP SHORT NEXT_SEARCH2
NEXT_SEARCH: ADD SI,SIZE FILE_RECORD
NEXT_SEARCH2: CMP BYTE PTR[SI],-1
JZ NO_MATCH
CMP [SI],AH
JNZ NEXT_SEARCH
POP DS
MOV BAR_ADDR,SI
MOV AX,LISTING_LEN
SHR AX,1
MOV BX,SIZE FILE_RECORD
MUL BX
SUB SI,AX
JNC STORE_MATCH
XOR SI,SI
STORE_MATCH: MOV LISTING_ADDR,SI
MOV FILE_CURRENT,FALSE
JMP SHORT SEARCH_END
NO_MATCH: POP DS
CALL BEEP
SEARCH_END: CALL DISP_LISTING
CALL DISP_FILE
RET
;----------------------------------------------;
L_DISPATCH DB UP_SCAN, DOWN_SCAN, PGUP_SCAN, PGDN_SCAN
DB HOME_SCAN, END_SCAN
L_LEN EQU $ - L_DISPATCH
DW LUP, LDOWN, LPGUP, LPGDN
DW LHOME, LEND
;----------------------------------------------;
; INPUT: AX=Listing page; BP=BAR_ADDR; DX=LISTING_ADDR; CX=LAST_ADDR.
; OUTPUT: LISTING_FLAG=TRUE if listing changed.
LUP: SUB BP,SIZE FILE_RECORD ;Move bar up a line.
JL LPAGE_END ;If < 0, ignore.
CMP BP,DX ;If bar below top, OK.
JAE LPAGE_UPDATE
SUB DX,SIZE FILE_RECORD ;Else, move listing up a line.
JMP SHORT LPAGE_UPDATE
LDOWN: ADD BP,SIZE FILE_RECORD ;Move bar down a line.
CMP BP,CX ;If > last line, then ignore.
JA LPAGE_END
ADD AX,DX ;Listing top + page length =
CMP BP,AX ; listing bottom; If bar below
JB LPAGE_UPDATE ; listing bottom, OK.
ADD DX,SIZE FILE_RECORD ;Else move listing down a line.
JMP SHORT LPAGE_UPDATE
LPGUP: SUB BP,AX ;Move bar up a page.
SUB DX,AX ;Move listing up a page.
JC LHOME ;If listing < top, then home.
JMP SHORT LPAGE_UPDATE ;Else, OK.
LPGDN: ADD DX,AX ;Move listing down a page.
CMP DX,CX ;If <= last line, do bar.
JBE DO_BAR
SUB DX,AX ;Else, back to where we were
MOV BP,CX ; and move bar to last line
JMP SHORT LPAGE_UPDATE ; and update.
DO_BAR: ADD BP,AX ;Move bar down a page.
CMP BP,CX ;If bar <= last line, OK.
JBE LPAGE_UPDATE
MOV BP,CX ;Else, move bar to last line.
JMP SHORT LPAGE_UPDATE
LHOME: XOR BP,BP ;Move bar to top.
XOR DX,DX ;Move listing to top.
JMP SHORT LPAGE_UPDATE
LEND: MOV BP,CX ;Move bar to last line.
ADD CX,SIZE FILE_RECORD ;Last line + 1 - page length =
SUB CX,AX ; top of last page.
CMP DX,CX ;If less than a full page,
JG LPAGE_UPDATE ; then already at last page.
MOV DX,CX ;Else, move listing to last page.
LPAGE_UPDATE: MOV BAR_ADDR,BP ;Store the new bar
MOV LISTING_ADDR,DX ; and listing line start.
MOV FILE_CURRENT,FALSE
MOV FAIL_FLAG,FALSE
LPAGE_END: RET
;----------------------------------------------;
FIND_FILES: CALL SET_ZIF
XOR BP,BP ;ES:BP -> filename storage.
MOV DX,OFFSET STAR_DOT_ZIF
XOR CX,CX
MOV AH,4EH ;Find first.
INT 21H
JC FILES_DONE ;If no, assumed right.
PUSH ES
MOV ES,FILENAME_SEG
XOR DI,DI
MOV AX,SPACE SHL 8 + SPACE
MOV CX,FILENAME_SIZE / 2 * KILOBYTES
REP STOSW ;Initialize with spaces.
POP ES
FIND_NEXT: MOV DX,OFFSET DTA.FILE_NAME
CALL READ_ZIF
JC FILES_DONE
CALL STORE_NAME ;Store a filename.
CMP BP,TEMP_RECORD - SIZE FILE_RECORD
JA FILES_DONE
MOV AH,4FH ;Find Next Matching.
INT 21H
JNC FIND_NEXT ;If successful store filename.
FILES_DONE: PUSH ES
MOV ES,FILENAME_SEG
MOV AX,-1 ;Else, mark the end with -1.
MOV DI,BP
STOSW
POP ES
SUB DI,SIZE FILE_RECORD + 2
JNC STORE_LAST
XOR DI,DI
STORE_LAST: MOV LAST_ADDR,DI
CALL SORT ;Sort 'em.
FILES_END: RET
;----------------------------------------------;
; INPUT: DX-> filename
; OUTPUT: CF = 1 if failed.
READ_ZIF: MOV AX,3D00H
INT 21H
JC OPEN_END
CMP FAIL_FLAG,TRUE
STC
JZ OPEN_FAIL
MOV BX,AX
CALL READZ
JNC OPEN_END
OPEN_FAIL: CALL BEEP
MOV FAIL_FLAG,FALSE
STC
OPEN_END: RET
;----------------------------------------------;
; INPUT: BX = filehandle.
; OUTPUT: CF=1 if read failed.
READZ: PUSH DS
MOV DS,ZIF_BUFF_SEG
XOR DX,DX
MOV CX,ZIF_BUFF_SIZE * KILOBYTES - 1
MOV AH,3FH
INT 21H
MOV CS:ZIF_BYTES,AX
MOV SI,AX
MOV BYTE PTR [SI],CTRL_Z
JC CLOSE
CMP CS:FAIL_FLAG,TRUE
STC
JZ CLOSE
CAPITALIZE: XOR SI,SI
MOV CX,AX
JCXZ CLOSE1
XOR AH,AH ;Quotes flag.
NEXT_CAP: LODSB
CMP AL,CTRL_Z
JZ CAP_END
CMP AL,AH
JZ CLOSE_QUOTES
CMP AH,DOUBLE_QUOTES
JZ NEXT_CAP
CMP AL,DOUBLE_QUOTES
JZ OPEN_QUOTES
CMP AL,"a"
JB NEXT_CAP
CMP AL,"z"
JA NEXT_CAP
AND BYTE PTR [SI - 1],5FH
JMP NEXT_CAP
OPEN_QUOTES: MOV AH,AL
JMP NEXT_CAP
CLOSE_QUOTES: XOR AH,AH
JMP NEXT_CAP
CAP_END:
CLOSE1: CLC
CLOSE: PUSHF
MOV AH,3EH
INT 21H
POPF
READ_END: POP DS
MOV FAIL_FLAG,FALSE
RET
;----------------------------------------------;
; INPUT: DX-> filename
; OUTPUT: CF = 1 if failed.
READ_PGM: MOV AX,3D00H
INT 21H
JC OPEN_END2
CMP FAIL_FLAG,TRUE
STC
JZ OPEN_FAIL2
MOV BX,AX
CALL READP
JNC OPEN_END
OPEN_FAIL2: CALL BEEP
MOV FAIL_FLAG,FALSE
STC
OPEN_END2: RET
;----------------------------------------------;
; INPUT: BX = filehandle.
; OUTPUT: CF=1 if read failed.
READP: PUSH DS
MOV DS,PGM_BUFF_SEG
XOR DX,DX
MOV CX,PGM_BUFF_SIZE * KILOBYTES - 1
MOV AH,3FH
INT 21H
JC CLOSE2
CMP CS:FAIL_FLAG,TRUE
STC
JZ CLOSE2
MOV CS:PGM_BYTES,AX
CLC
CLOSE2: PUSHF
MOV AH,3EH
INT 21H
POPF
READP_END: POP DS
MOV FAIL_FLAG,FALSE
RET
;----------------------------------------------;
;INPUT: BP->filename storage.
;OUTPUT: BP->next storage.
FILE_STR DB "[FILE]"
FILE_STR_LEN EQU $ - FILE_STR
FILENAME_STR DB "FILENAME"
FILENAME_STR_LEN EQU $ - FILENAME_STR
STORE_NAME: PUSH DS
MOV DS,ZIF_BUFF_SEG
XOR BX,BX
NEXT_FILE_STR: MOV DI,OFFSET FILE_STR
MOV SI,BX
CMP BYTE PTR [SI],CTRL_Z
JZ NAME_END1
INC BX
MOV CX,FILE_STR_LEN
REPZ CMPSB
JNZ NEXT_FILE_STR
ADD BX,FILE_STR_LEN - 1
MOV SI,BX
CALL PARSE_LINES
MOV BX,SI
NEXT_FILE_STR2:MOV DI,OFFSET FILENAME_STR
MOV SI,BX
CMP BYTE PTR [SI],CTRL_Z
JZ NAME_END1
CMP BYTE PTR [SI],"["
JZ NAME_END1
INC BX
MOV CX,FILENAME_STR_LEN
REPZ CMPSB
JNZ NEXT_FILE_STR2
CALL PARSE_LINE ;SI-> name start.
JC NAME_END1
PUSH ES ;Preserve extra segment.
MOV ES,CS:FILENAME_SEG
MOV DI,BP
MOV CX,SIZE LIST_NAME ;Store 12 bytes of filename.
JMP SHORT NEXT_STORE
EXTENSION: ADD DI,CX
MOV CX,3
SUB DI,CX
NEXT_STORE: LODSB ;Get a byte.
CMP AL,SPACE
JBE END_STORE ;If yes, finish with blanks.
CMP AL,"." ;Is it the period?
JZ EXTENSION
STOSB ;Store byte.
LOOP NEXT_STORE ;Get next byte.
END_STORE: ADD BP,SIZE LIST_NAME
INC CS:FILE_CNT
POP ES
NAME_END1: POP DS
NAME_END: RET ;Done here.
;----------------------------------------------;
DISP_FILE: CMP FILE_CURRENT,TRUE
JZ DISP_FILE2
CALL MAKE_ZIF_NAME
MOV DX,OFFSET ASCIIZ_NAME
CALL READ_ZIF
JC NO_FILE
MOV FILE_CURRENT,TRUE
CALL PARSE_FILE
DISP_FILE2: CALL DISP_CUSTOM
JMP SHORT DISP_FILE_END
NO_FILE: CALL CLEAR_FILE
CALL BEEP
DISP_FILE_END: RET
;----------------------------------------------;
ACTIVE EQU 0
INACTIVE EQU -1
CAT STRUC
CAT_STATUS DB INACTIVE
CAT_LEN DB ?
CAT_TEXT DB " "
CAT_NUL DB 0
CAT_MENU DW ?
CAT_PARSE DW ?
CAT ENDS
CATEGORY CAT <,5, "FILE]",, DUMMY_RET, FILE_PARSE>
CAT <,6, "COLOR]",, COLOR_MENU, COLOR_PARSE>
CAT <,7, "HOTKEY]",, HOTKEY_MENU, HOTKEY_PARSE>
CAT <,6, "MODEM]",, MODEM_MENU, MODEM_PARSE>
CAT <,8, "PRINTER]",, PRINTER_MENU, PRINTER_PARSE>
CAT <,5, "TEXT]",, TEXT_MENU, TEXT_PARSE>
CAT <,7, "NUMBER]",, NUMBER_MENU, NUMBER_PARSE>
CAT <,10,"PICK LIST]",, PICK_MENU, PICK_PARSE>
CAT_END EQU $
CATEGORY_LEN EQU (CAT_END - CATEGORY ) / SIZE CAT
CUSTOM_ADDR DW ? ;Index into custom menu.
VARS LABEL BYTE
FILE_SIZE DW ?,?
COLOR_MAX EQU 7
COLOR_MENUS DW COLOR_MAX DUP (?)
TEXT_MAX EQU 7
TEXT_MENUS DW TEXT_MAX DUP (?)
NUM_MAX EQU 7
NUMBER_MENUS DW NUM_MAX DUP (?)
PICK_MAX EQU 6
PICK_MENUS DW PICK_MAX DUP (?)
ENTRY_MENUS DW PICK_MAX DUP (PICK_MAX DUP (?))
SHIFT_ADDR DW ?
SHIFT_TEXT_ADDR DW ?
SCAN_ADDR DW ?
SCAN_TEXT_ADDR DW ?
VARS_LEN EQU $ - VARS
COLOR_ADDRS DW COLOR_MAX DUP (?)
COLOR_VALUES DW COLOR_MAX DUP (?)
TEXT_ADDRS DW TEXT_MAX DUP (?)
TEXT_LENGTH DW TEXT_MAX DUP (?)
STRING_MAX EQU 27
TEXT_EDIT DB TEXT_MAX DUP (STRING_MAX DUP (?))
NUMBER_ADDRS DW NUM_MAX DUP (?)
NUMBER_TYPE DW NUM_MAX DUP (?)
RANGE_LOW DW NUM_MAX DUP (?)
RANGE_HIGH DW NUM_MAX DUP (?)
INTEGER_MAX EQU 7
NUMBER_EDIT DB NUM_MAX DUP (INTEGER_MAX DUP (?))
NUMBER_RANGE DB INTEGER_MAX + 1 DUP (?)
PICK_ADDRS DW PICK_MAX DUP (?)
PICK_TYPES DW PICK_MAX DUP (?)
ENTRY_VALUES DW PICK_MAX DUP (PICK_MAX DUP (?))
;--------------;
INIT_VARS: MOV CUSTOM_ADDR,OFFSET CATEGORY + SIZE CAT
MOV BP,CATEGORY_LEN
MOV SI,OFFSET CATEGORY
MOV AX,INACTIVE
NEXT_INACTIVE: MOV [SI],AL
ADD SI,SIZE CAT
DEC BP
JNZ NEXT_INACTIVE
MOV CX,VARS_LEN
MOV DI,OFFSET VARS
REP STOSB
RET
;----------------------------------------------;
PARSE_FILE: PUSH DS
CALL INIT_VARS
MOV DS,ZIF_BUFF_SEG
XOR SI,SI
NEXT_BRACKET: LODSB
CMP AL,CTRL_Z
JZ PARSE_FILE_END
CMP AL,"["
JNZ NEXT_BRACKET
CMP BYTE PTR [SI],CTRL_Z
JZ PARSE_FILE_END
MOV BP,CATEGORY_LEN
MOV DX,SI
MOV BX,OFFSET CATEGORY
NEXT_CAT: MOV SI,DX
MOV DI,BX
ADD DI,CAT_TEXT
MOV CL,CS:[BX.CAT_LEN]
XOR CH,CH
REP CMPSB
JZ FOUND_CAT
ADD BX,SIZE CAT
DEC BP
JNZ NEXT_CAT
INC DX
MOV SI,DX
JMP NEXT_BRACKET
FOUND_CAT: CALL PARSE_LINES
JC NEXT_BRACKET
PUSH BX
CALL CS:[BX.CAT_PARSE]
POP BX
JC NEXT_BRACKET
MOV CS:[BX.CAT_STATUS],ACTIVE
JMP NEXT_BRACKET
PARSE_FILE_END:POP DS
RET
;----------------------------------------------;
;INPUT: DS:SI->ZIF_BUFF_SEG:OFFSET; BX->CATEGORY:OFFSET
;OUTPUT: DS:SI->end of category; CF=1 if no valid parameters found.
SIZE_STR DB "SIZE"
SIZE_STR_LEN EQU $ - SIZE_STR
;--------------;
FILE_PARSE: MOV BP,SIZE_STR_LEN
MOV BX,OFFSET SIZE_STR
CALL PARSE_KEY
JC FILE_PARSE_END
CALL GET_NUMBER
JC FILE_PARSE_END
MOV CS:FILE_SIZE[0],AX
MOV CS:FILE_SIZE[2],CX
FILE_PARSE_END:RET
;--------------;
ENTRY_INDEX DW ?
PICK_ADDR DW ?
PICK_PARSE: XOR BX,BX
MOV CS:ENTRY_INDEX,0
NEXT_PICK: MOV BP,SI
INC BP
CALL PARSE_STRING
JC PICK_END
CALL PARSE_LINE
JC PICK_END
CALL GET_NUMBER
JC PICK_END
SUB AX,100H
JC PICK_END
MOV CS:PICK_ADDR,AX
CALL PARSE_LINE
JC PICK_END
PUSH BX
PUSH BP
MOV BP,SIZE_STR_LEN
MOV BX,OFFSET SIZE_STR
CALL PARSE_KEY
POP BP
POP BX
JC PICK_END
CALL PARSE_LINE
JC PICK_END
LODSB
CMP AL,"B"
JZ STORE_PICK
CMP AL,"W"
STC
JNZ PICK_END
STORE_PICK: MOV CS:PICK_TYPES[BX],AX
CALL PARSE_END2
CALL PARSE_LINES
JC PICK_END
CALL PARSE_ENTRY
JC PICK_END
MOV AX,CS:PICK_ADDR
MOV CS:PICK_ADDRS[BX],AX
MOV CS:PICK_MENUS[BX],BP
ADD CS:ENTRY_INDEX,PICK_MAX * 2
INC BX
INC BX
CMP BX,PICK_MAX * 2
JAE PICK_END
CALL PARSE_LINES
JNC NEXT_PICK
CLC
PICK_END: RET
;--------------;
ENTRY_STR DB "ENTRY"
ENTRY_STR_LEN EQU $ - ENTRY_STR
VALUE_STR DB "VALUE"
VALUE_STR_LEN EQU $ - VALUE_STR
ENTRY_ADDR DW ?
ENTRY_MAX DW ?
PARSE_ENTRY: PUSH BX
PUSH BP
MOV BX,CS:ENTRY_INDEX
MOV AX,BX
ADD AX,PICK_MAX * 2
MOV CS:ENTRY_MAX,AX
NEXT_ENTRY: PUSH BX
MOV BP,ENTRY_STR_LEN
MOV BX,OFFSET ENTRY_STR
CALL PARSE_KEY
POP BX
JC PARSE_E_END
CALL PARSE_LINE
JC PARSE_E_END
MOV BP,SI
INC BP
CALL PARSE_STRING
JC PARSE_E_END
CALL PARSE_LINE
JC PARSE_E_END
PUSH BX
PUSH BP
MOV BP,VALUE_STR_LEN
MOV BX,OFFSET VALUE_STR
CALL PARSE_KEY
POP BP
POP BX
JC PARSE_E_END
CALL PARSE_LINE
JC PARSE_E_END
CALL GET_NUMBER
JC PARSE_E_END
MOV CS:ENTRY_VALUES[BX],AX
MOV CS:ENTRY_MENUS[BX],BP
INC BX
INC BX
CMP BX,CS:ENTRY_MAX
JAE PARSE_E_END
CALL PARSE_LINES
JC PARSE_E_DONE
CMP AL,DOUBLE_QUOTES
JNZ NEXT_ENTRY
PARSE_E_DONE: CLC
PARSE_E_END: POP BP
POP BX
RET
;--------------;
COLOR_PARSE: XOR BX,BX ;Index.
NEXT_COLOR: MOV BP,SI ;Save string start.
INC BP ;Bump past quotes.
CALL PARSE_STRING
JC COLOR_END
CALL PARSE_LINE
JC COLOR_END
CALL GET_NUMBER
JC COLOR_END
SUB AX,100H
JC COLOR_END
MOV CS:COLOR_MENUS[BX],BP ;String start.
MOV CS:COLOR_ADDRS[BX],AX ;Prog address.
INC BX
INC BX
CMP BX,COLOR_MAX * 2
JAE COLOR_END
CALL PARSE_LINES
JNC NEXT_COLOR
CLC
COLOR_END: RET
;--------------;
SHIFT_STR DB "SHIFT"
SHIFT_LEN EQU $ - SHIFT_STR
TEXT_STR DB "TEXT"
TEXT_LEN EQU $ - TEXT_STR
SCAN_STR DB "SCAN"
SCAN_LEN EQU $ - SCAN_STR
GOOD_PARA DB FALSE ;TRUE if valid parameters
HOTKEY_PARSE: MOV CS:GOOD_PARA,FALSE
PUSH SI
NEXT_SHIFT: MOV BP,SHIFT_LEN
MOV BX,OFFSET SHIFT_STR
CALL PARSE_KEY
JNC GOT_SHIFT
CALL PARSE_LINES
JNC NEXT_SHIFT
JMP SHORT CK_SCAN
GOT_SHIFT: CALL PARSE_LINE
JC CK_SCAN
CALL GET_NUMBER
JC CK_SCAN
SUB AX,100H
JC CK_SCAN
MOV CS:SHIFT_ADDR,AX
MOV CS:GOOD_PARA,TRUE
CALL PARSE_LINE
JC CK_SCAN
MOV BP,TEXT_LEN
MOV BX,OFFSET TEXT_STR
CALL PARSE_KEY
JC CK_SCAN
CALL PARSE_LINE
JC CK_SCAN
CALL GET_NUMBER
JC CK_SCAN
SUB AX,100H
JC CK_SCAN
MOV CS:SHIFT_TEXT_ADDR,AX
CK_SCAN: POP SI
NEXT_SCAN: MOV BP,SCAN_LEN
MOV BX,OFFSET SCAN_STR
CALL PARSE_KEY
JNC GOT_SCAN
CALL PARSE_LINES
JNC NEXT_SCAN
JMP SHORT HOT_END1
GOT_SCAN: CALL PARSE_LINE
JC HOT_END1
CALL GET_NUMBER
JC HOT_END1
SUB AX,100H
JC HOT_END1
MOV CS:SCAN_ADDR,AX
CALL PARSE_LINE
JC HOT_END1
MOV BP,TEXT_LEN
MOV BX,OFFSET TEXT_STR
CALL PARSE_KEY
JC HOT_END1
CALL PARSE_LINE
JC HOT_END1
CALL GET_NUMBER
JC HOT_END1
SUB AX,100H
JC HOT_END1
MOV CS:SCAN_TEXT_ADDR,AX
HOT_END1: CMP CS:GOOD_PARA,TRUE
CLC
JZ HOT_END
STC
HOT_END: RET
;--------------;
COM_STR DB "COM"
COM_LEN EQU $ - COM_STR
COM_ADDR DW ?
MODEM_PARSE: MOV BP,COM_LEN
MOV BX,OFFSET COM_STR
CALL PARSE_KEY
JC MODEM_END
CALL PARSE_LINE
JC MODEM_END
CALL GET_NUMBER
JC MODEM_END
SUB AX,100H
JC MODEM_END
MOV CS:COM_ADDR,AX
MODEM_END: RET
;--------------;
LPT_STR DB "LPT"
LPT_LEN EQU $ - LPT_STR
LPT_ADDR DW ?
PRINTER_PARSE: MOV BP,LPT_LEN
MOV BX,OFFSET LPT_STR
CALL PARSE_KEY
JC LPT_END
CALL PARSE_LINE
JC LPT_END
CALL GET_NUMBER
JC LPT_END
SUB AX,100H
JC LPT_END
MOV CS:LPT_ADDR,AX
LPT_END: RET
RET
;--------------;
LENGTH_STR DB "LENGTH"
LENGTH_STR_LEN EQU $ - LENGTH_STR
TEXT_PARSE: XOR BX,BX ;Index.
NEXT_TEXT: MOV BP,SI ;Save string start.
INC BP ;Bump past quotes.
CALL PARSE_STRING
JC TEXT_END
CALL PARSE_LINE
JC TEXT_END
CALL GET_NUMBER
JC TEXT_END
SUB AX,100H
JC TEXT_END
MOV CS:TEXT_ADDRS[BX],AX ;Prog address.
CALL PARSE_LINE
JC TEXT_END
PUSH BX
PUSH BP
MOV BP,LENGTH_STR_LEN
MOV BX,OFFSET LENGTH_STR
CALL PARSE_KEY
POP BP
POP BX
JC TEXT_END
CALL PARSE_LINE
JC TEXT_END
CALL GET_NUMBER
JC TEXT_END
MOV CS:TEXT_LENGTH[BX],AX
MOV CS:TEXT_MENUS[BX],BP ;String start.
INC BX
INC BX
CMP BX,TEXT_MAX * 2
JAE TEXT_END
CALL PARSE_LINES
JNC NEXT_TEXT
CLC
TEXT_END: RET
;--------------;
RANGE_STR DB "RANGE"
RANGE_STR_LEN EQU $ - RANGE_STR
NUMBER_PARSE: XOR BX,BX ;Index.
NEXT_NUM: MOV BP,SI ;Save string start.
INC BP ;Bump past quotes.
CALL PARSE_STRING
JC LILLY_N_END
CALL PARSE_LINE
JC LILLY_N_END
CALL GET_NUMBER
JC LILLY_N_END
SUB AX,100H
JC LILLY_N_END
MOV CS:NUMBER_ADDRS[BX],AX
CALL PARSE_LINE
JC LILLY_N_END
PUSH BX
PUSH BP
MOV BP,SIZE_STR_LEN
MOV BX,OFFSET SIZE_STR
CALL PARSE_KEY
POP BP
POP BX
JC LILLY_N_END
CALL PARSE_LINE
JC LILLY_N_END
LODSB
CMP AL,"B"
JZ STORE_NUMBER
CMP AL,"W"
JZ STORE_NUMBER
LILLY_N_END: STC
JMP SHORT N_END
STORE_NUMBER: MOV CS:NUMBER_TYPE[BX],AX
MOV CS:NUMBER_MENUS[BX],BP ;String start.
MOV CS:RANGE_LOW[BX],0
MOV CX,-1
CMP AL,"W"
JZ STORE_RANGE
MOV CX,255
STORE_RANGE: MOV CS:RANGE_HIGH[BX],CX
MOV CX,4
NEXT_SIZE2: LODSB
CMP AL,SPACE
JBE DO_RANGE
LOOP NEXT_SIZE2
DO_RANGE: DEC SI
CALL PARSE_LINE
JC NEXT_NUM2
PUSH BX
PUSH BP
MOV BP,RANGE_STR_LEN
MOV BX,OFFSET RANGE_STR
CALL PARSE_KEY
POP BP
POP BX
JC NEXT_NUM2
CALL PARSE_LINE
JC NEXT_NUM2
CMP BYTE PTR [SI],"-"
JNZ GET_LOW
INC SI
JMP SHORT GET_HIGH
GET_LOW: CALL PARSE_LINE
JC NEXT_NUM2
CALL GET_NUMBER
JC NEXT_NUM2
MOV CS:RANGE_LOW[BX],AX
GET_HIGH: CALL PARSE_LINE
JC NEXT_NUM2
CALL GET_NUMBER
JC NEXT_NUM2
MOV CS:RANGE_HIGH[BX],AX
NEXT_NUM2: INC BX
INC BX
CMP BX,NUM_MAX * 2
JAE N_END
CALL PARSE_END2
CALL PARSE_LINES
JC N_END2
JMP NEXT_NUM
N_END2: CLC
N_END: RET
;----------------------------------------------;
; INPUT: DS:SI-> String OUTPUT: CF=1 if no string.
PARSE_STRING: MOV AH,DOUBLE_QUOTES
CMP BYTE PTR [SI],AH
JNZ NO_STRING
INC SI
NEXT_STRING: LODSB
CMP AL,CTRL_Z
JZ NO_STRING1
CMP AL,CR
JZ NO_STRING
CMP AL,AH
JNZ NEXT_STRING
MOV BYTE PTR [SI-1],0 ;ASCIIZ string
CLC
JMP SHORT STRING_END
NO_STRING1: DEC SI
NO_STRING: STC
STRING_END: RET
;----------------------------------------------;
; INPUT: ES:BX->string to match; BP=string len; DS:SI-> FILEBUFF.
; OUTPUT: CF=1 if no match; CF=0 if match; SI-> next string.
PARSE_KEY: MOV AL,[SI]
CMP AL,CTRL_Z
JZ NO_KEY
CMP AL,"["
JZ NO_KEY
MOV CX,BP
MOV DI,BX
MOV AX,SI
REP CMPSB
JZ FOUND_KEY
MOV SI,AX
PUSH BX
CALL PARSE_END2
CALL PARSE_LINES
POP BX
JMP PARSE_KEY
FOUND_KEY: CALL PARSE_LINE
RET
NO_KEY: STC
RET
;----------------------------------------------;
PARSE_END2: LODSB
CMP AL,LF
JZ PARSE_END_END
CMP AL,CTRL_Z
JNZ PARSE_END2
DEC SI
PARSE_END_END: RET
;--------------;
PICK_M1 LABEL BYTE
DB "Select pick description then press Enter to pick. Esc to Exit",0
PICK_M DB "Pick descriptions",0
DB "~~~~~~~~~~~~~~~~~",0
PICK_INDEX DW ?
PICK_MENU: CMP [PICK_MENUS],INACTIVE
JZ P_MENU_END1
MOV PICK_INDEX,0
NEXT_P_MENU: MOV STATE,CUSTOM_TYPE
MOV SI,OFFSET PICK_M1
CALL DISPLAY_MENU
NEXT_P_MENU2: CALL DISP_PICK
CALL GETKEY
JC P_MENU_END
CMP AL,LEFT_SCAN
JZ P_MENU_END
CMP AH,CR
JZ DO_PICK
CMP AL,RIGHT_SCAN
JZ DO_PICK
CK_P_UP: MOV BX,PICK_INDEX
CMP AL,UP_SCAN
JNZ CK_P_DN
SUB BX,2
JC NEXT_P_MENU2
JMP SHORT PICK_UPDATE
CK_P_DN: CMP AL,DOWN_SCAN
JNZ NEXT_P_MENU2
INC BX
INC BX
CMP BX,PICK_MAX * 2
JAE NEXT_P_MENU2
CMP PICK_MENUS[BX],INACTIVE
JZ NEXT_P_MENU2
PICK_UPDATE: MOV PICK_INDEX,BX
JMP NEXT_P_MENU2
DO_PICK: CALL PICK_SELECT
JMP NEXT_P_MENU
P_MENU_END1: CALL BEEP
P_MENU_END: RET
;----------------------------------------------;
DISP_PICK: MOV AX,PICK_TOP
CALL CALC_ADDR
ADD DI,SELECT_START
MOV BH,COLOR.W
PUSH DI
MOV SI,OFFSET PICK_M
CALL WRITE_STRING
POP DI
ADD DI,CRT_WIDTH
PUSH DI
CALL WRITE_STRING
POP DI
;--------------;
XOR BP,BP
NEXT_PICK_DES: MOV SI,PICK_MENUS[BP]
CMP SI,INACTIVE
JZ PICK_DES_END
ADD DI,CRT_WIDTH
PUSH DI
MOV CX,STRING_MAX
MOV BH,COLOR.W
CMP PICK_INDEX,BP
JNZ WRITE_DESC4
MOV BH,COLOR.C
CMP STATE,CUSTOM_TYPE
JZ WRITE_DESC4
MOV BH,COLOR.A
WRITE_DESC4: PUSH DS
MOV DS,ZIF_BUFF_SEG
CALL WRITE_LINE
CALL PAD_LINE
POP DS
POP DI
INC BP
INC BP
CMP BP,PICK_MAX * 2
JB NEXT_PICK_DES
PICK_DES_END: RET
;----------------------------------------------;
PICK_M2 LABEL BYTE
DB "Pick entry then press Enter to select. Esc to Cancel",0
ENTRY_SELECT_HOME DW ?
ENTRY_SELECT_INDEX DW ?
PICK_SELECT: MOV STATE,SELECT_TYPE
MOV SI,OFFSET PICK_M2
CALL DISPLAY_MENU
CALL DISP_PICK
MOV AX,PICK_MAX
MOV BX,PICK_INDEX ;BX=Pick index.
MUL BX
MOV BP,AX ;BP=Entry index.
MOV ENTRY_SELECT_HOME,BP
MOV SI,PICK_ADDRS[BX]
PUSH DS
MOV DS,PGM_BUFF_SEG
MOV AX,[SI] ;Current value.
POP DS
NEXT_P_DEF: CMP CS:ENTRY_MENUS[BP],INACTIVE
JZ FOUND_DEF1
CMP BYTE PTR PICK_TYPES[BX],"W"
JZ CK_WORD
CMP BYTE PTR CS:ENTRY_VALUES[BP],AL
JZ FOUND_DEF
JMP SHORT LOOP_DEF
CK_WORD: CMP CS:ENTRY_VALUES[BP],AX
JZ FOUND_DEF
LOOP_DEF: INC SI
INC SI
INC BP
INC BP
JMP NEXT_P_DEF
FOUND_DEF1: DEC BP
DEC BP
FOUND_DEF: MOV ENTRY_SELECT_INDEX,BP
NEXT_P_SEL: CALL DISP_SELECT
CALL GETKEY
JC PICK_S_END
CMP AL,LEFT_SCAN
JZ PICK_S_END
CMP AH,CR
JZ DO_S_PICK
CK_S_UP: MOV BX,ENTRY_SELECT_INDEX
CMP AL,UP_SCAN
JNZ CK_S_DN
SUB BX,2
JC NEXT_P_SEL
CMP BX,ENTRY_SELECT_HOME
JB NEXT_P_SEL
JMP SHORT ENTRY_UPDATE
CK_S_DN: CMP AL,DOWN_SCAN
JNZ NEXT_P_SEL
INC BX
INC BX
CMP ENTRY_MENUS[BX],INACTIVE
JZ NEXT_P_SEL
ENTRY_UPDATE: MOV ENTRY_SELECT_INDEX,BX
JMP NEXT_P_SEL
DO_S_PICK: MOV MODIFY_FLAG,TRUE
PICK_S_END: CALL CK_MODIFIED
JC P_S_END
CALL COPY_PICK
CALL SAVE
P_S_END: CALL CLEAR_PICK
RET
;----------------------;
DISP_SELECT: MOV AX,PICK_INDEX
SHR AX,1
ADD AX,PICK_TOP + 2
CALL CALC_ADDR
ADD DI,SELECT_START + (STRING_MAX * 2)
MOV BP,ENTRY_SELECT_HOME
NEXT_SEL_DES: MOV SI,ENTRY_MENUS[BP]
CMP SI,INACTIVE
JZ SELECT_DES_END
PUSH DI
MOV CX,STRING_MAX
MOV BH,COLOR.W
CMP ENTRY_SELECT_INDEX,BP
JNZ WRITE_DESC6
MOV BH,COLOR.C
WRITE_DESC6: PUSH DS
MOV DS,ZIF_BUFF_SEG
CALL WRITE_LINE
CALL PAD_LINE
POP DS
POP DI
ADD DI,CRT_WIDTH
INC BP
INC BP
JMP NEXT_SEL_DES
SELECT_DES_END:RET
;----------------------------------------------;
COPY_PICK: PUSH ES
MOV ES,PGM_BUFF_SEG
MOV SI,PICK_INDEX
MOV DI,PICK_ADDRS[SI]
CMP BYTE PTR PICK_TYPES[SI],"W"
MOV SI,ENTRY_SELECT_INDEX
MOV AX,ENTRY_VALUES[SI]
JZ COPY_WORD2
STOSB
JMP SHORT COPY_P_END
COPY_WORD2: STOSW
COPY_P_END: POP ES
RET
;----------------------------------------------;
CLEAR_PICK: MOV AX,PICK_INDEX
SHR AX,1
ADD AX,PICK_TOP + 2
CALL CALC_ADDR
ADD DI,SELECT_START + (STRING_MAX * 2)
PUSH ES
MOV DX,STATUS_REG ;Retrieve status register.
MOV ES,VIDEO_SEG ;Point to screen segment.
MOV SI,COLOR_INDEX
MOV BH,COLOR.W
MOV AL,SPACE
MOV BP,PICK_MAX
NEXT_CLEAR5: PUSH DI
MOV CX,STRING_MAX
NEXT_CLEAR6: CALL WRITE_CHAR
LOOP NEXT_CLEAR6
POP DI
ADD DI,CRT_WIDTH
DEC BP
JNZ NEXT_CLEAR5
POP ES
RET
;----------------------------------------------;
COLOR_M1 LABEL BYTE
DB "Select color description then press Enter to change color. Esc to Exit",0
COLOR_M DB "Color Descriptions",0
DB "~~~~~ ~~~~~~~~~~~~",0
COLOR_INDEX DW 0
COLOR_MENU: CMP [COLOR_MENUS],INACTIVE
JZ C_MENU_END1
CALL COLOR_DEFAULT
MOV COLOR_INDEX,0
NEXT_C_MENU: MOV STATE,CUSTOM_TYPE
MOV SI,OFFSET COLOR_M1
CALL DISPLAY_MENU
NEXT_C_MENU2: CALL DISP_COLOR
CALL GETKEY
JC C_MENU_END
CMP AL,LEFT_SCAN
JZ C_MENU_END
CMP AH,CR
JZ DO_COLOR
CMP AL,RIGHT_SCAN
JZ DO_COLOR
CK_C_UP: MOV BX,COLOR_INDEX
CMP AL,UP_SCAN
JNZ CK_C_DN
SUB BX,2
JC NEXT_C_MENU2
JMP SHORT COLOR_UPDATE
CK_C_DN: CMP AL,DOWN_SCAN
JNZ NEXT_C_MENU2
INC BX
INC BX
CMP BX,COLOR_MAX * 2
JAE NEXT_C_MENU2
CMP COLOR_MENUS[BX],INACTIVE
JZ NEXT_C_MENU2
COLOR_UPDATE: MOV COLOR_INDEX,BX
JMP NEXT_C_MENU2
DO_COLOR: CALL COLOR_SELECT
JMP NEXT_C_MENU
C_MENU_END1: CALL BEEP
C_MENU_END: CALL CK_MODIFIED
JC C_M_END
CALL COPY_COLORS
CALL SAVE
C_M_END: RET
;--------------;
COLOR_DEFAULT: PUSH ES
MOV ES,PGM_BUFF_SEG
XOR BX,BX
NEXT_C_DEFAULT:CMP [COLOR_MENUS.BX],INACTIVE
JZ C_DEFAULT_END
MOV SI,[COLOR_ADDRS.BX]
MOV AX,ES:[SI]
MOV [COLOR_VALUES.BX],AX
INC BX
INC BX
CMP BX,COLOR_MAX * 2
JB NEXT_C_DEFAULT
C_DEFAULT_END: POP ES
RET
;--------------;
DISP_COLOR: PUSH DS
MOV AX,COLOR_TOP
CALL CALC_ADDR
ADD DI,SELECT_START
MOV BH,COLOR.W
PUSH DI
MOV SI,OFFSET COLOR_M
CALL WRITE_STRING
POP DI
ADD DI,CRT_WIDTH
PUSH DI
CALL WRITE_STRING
POP DI
;--------------;
XOR BP,BP
MOV DS,ZIF_BUFF_SEG
NEXT_COLOR_DES:MOV SI,CS:COLOR_MENUS[BP]
CMP SI,INACTIVE
JZ COLOR_DES_END
ADD DI,CS:CRT_WIDTH
PUSH DI
MOV BX,CS:COLOR_VALUES[BP]
XCHG BH,BL
MOV AL,SPACE
CALL WRITE_SCREEN
MOV AL,"["
CALL WRITE_SCREEN
MOV AX,BP
SHR AX,1
ADD AL,"A"
CALL WRITE_SCREEN
MOV AL,"]"
CALL WRITE_SCREEN
MOV AL,SPACE
CALL WRITE_SCREEN
MOV BH,CS:COLOR.W
CALL WRITE_SCREEN
CMP CS:COLOR_INDEX,BP
JNZ WRITE_DESC
MOV BH,CS:COLOR.C
CMP CS:STATE,CUSTOM_TYPE
JZ WRITE_DESC
MOV BH,CS:COLOR.A
WRITE_DESC: CALL WRITE_STRING
POP DI
INC BP
INC BP
CMP BP,COLOR_MAX * 2
JB NEXT_COLOR_DES
COLOR_DES_END: POP DS
RET
;----------------------------------------------;
COLOR_M2 LABEL BYTE
DB "Select color then press Enter. Esc to Cancel",0
COLOR_SELECT: MOV SI,COLOR_INDEX
PUSH COLOR_VALUES[SI]
MOV STATE,SELECT_TYPE
MOV SI,OFFSET COLOR_M2
CALL DISPLAY_MENU
NEXT_C_BARS: CALL DISP_COLOR
MOV AX,COLOR_TOP + COLOR_MAX + 2
CALL CALC_ADDR
ADD DI,SELECT_START
PUSH ES
MOV DX,STATUS_REG ;Retrieve status register.
MOV ES,VIDEO_SEG ;Point to screen segment.
MOV SI,COLOR_INDEX
XOR BH,BH
N_BACKGROUND: PUSH DI
N_FORGROUND: MOV AL,SPACE
CALL WRITE_CHAR
MOV AL,"*"
CMP BH,BYTE PTR COLOR_VALUES[SI]
JNZ DO_A_COLOR
MOV AX,COLOR_INDEX
SHR AL,1
ADD AL,"A"
DO_A_COLOR: CALL WRITE_CHAR
MOV AL,SPACE
CALL WRITE_CHAR
INC BH
TEST BH,1111B
JNZ N_FORGROUND
POP DI
ADD DI,CRT_WIDTH
TEST BH,10000000B
JZ N_BACKGROUND
POP ES
NEXT_C_KEY: CALL GETKEY
JC COLOR_S_END1
CMP AH,CR
JZ SELECT_ENTER
MOV CX,COLOR_VALUES[SI]
MOV BH,CL
MOV BL,CL
AND BH,11110000B ;Background
AND BL,00001111B ;Foreground
CMP AL,UP_SCAN
JNZ CK_COLOR_DN
SUB BH,00010000B
JC NEXT_C_KEY
JMP SHORT UPDATE_C
CK_COLOR_DN: CMP AL,DOWN_SCAN
JNZ CK_COLOR_RT
ADD BH,00010000B
TEST BH,10000000B
JNZ NEXT_C_KEY
JMP SHORT UPDATE_C
CK_COLOR_RT: CMP AL,RIGHT_SCAN
JNZ CK_COLOR_LT
ADD BL,1
TEST BL,00010000B
JNZ NEXT_C_KEY
JMP SHORT UPDATE_C
CK_COLOR_LT: CMP AL,LEFT_SCAN
JNZ NEXT_C_KEY
SUB BL,1
JC NEXT_C_KEY
UPDATE_C: OR BL,BH
MOV CL,BL
MOV COLOR_VALUES[SI],CX
JMP NEXT_C_BARS
SELECT_ENTER: POP AX
MOV MODIFY_FLAG,TRUE
JMP SHORT COLOR_S_END
COLOR_S_END1: MOV SI,COLOR_INDEX
POP COLOR_VALUES[SI]
COLOR_S_END: CALL CLEAR_BARS
RET
;----------------------------------------------;
CLEAR_BARS: MOV AX,COLOR_TOP + COLOR_MAX + 2
CALL CALC_ADDR
ADD DI,SELECT_START
PUSH ES
MOV DX,STATUS_REG ;Retrieve status register.
MOV ES,VIDEO_SEG ;Point to screen segment.
MOV SI,COLOR_INDEX
MOV BH,COLOR.W
MOV AL,SPACE
MOV BP,8
NEXT_CLEAR3: PUSH DI
MOV CX,16 * 3
NEXT_CLEAR4: CALL WRITE_CHAR
LOOP NEXT_CLEAR4
POP DI
ADD DI,CRT_WIDTH
DEC BP
JNZ NEXT_CLEAR3
POP ES
RET
;----------------------------------------------;
COPY_COLORS: PUSH ES
MOV ES,PGM_BUFF_SEG
XOR BX,BX
NEXT_C_COPY: CMP COLOR_MENUS[BX],INACTIVE
JZ COPY_C_END
MOV DI,COLOR_ADDRS[BX]
MOV AX,COLOR_VALUES[BX]
STOSB
INC BX
INC BX
JMP NEXT_C_COPY
COPY_C_END: POP ES
RET
;----------------------------------------------;
SCAN_CODES LABEL BYTE
DB "1",2,"2",3,"3",4,"4",5,"5",6,"6",7,"7",8,"8",9,"9",0AH,"0",0BH,"-",0CH
DB "=",0DH,"Q",10H,"W",11H,"E",12H,"R",13H,"T",14H,"Y",15H,"U",16H,"I",17H
DB "O",18H,"P",19H,"[",1AH,"]",1BH,"A",1EH,"S",1FH,"D",20H,"F",21H,"G",22H
DB "H",23H,"J",24H,"K",25H,"L",26H,";",27H,39,28H,96,29H,"\",2BH,"Z",2CH
DB "X",2DH,"C",2EH,"V",2FH,"B",30H,"N",31H,"M",32H,",",33H,".",34H,"/",35H
SCAN_COUNT EQU ($ - SCAN_CODES) / 2
;--------------;
HOT_MENU LABEL BYTE
DB "Current hotkey is ",0
HOT_MENU2 LABEL BYTE
DB "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",0
HOT_MENU3 LABEL BYTE
DB "Select HotKey and then press Enter. Esc to cancel",0
HOT_MENU4 LABEL BYTE
DB "Select Shift key and then press Enter. Esc to cancel",0
HOT_MENU5 LABEL BYTE
DB "Press Alpha or Numeric key. Esc to cancel",0
SHIFT_TEXT DB "CtRs", "CtLs", "AlRs", "AlLs", "RsLs", "CtAl"
CTRL DB "Ctrl ",0
ALT DB "Alt ",0
RT_SHIFT DB "Right Shift ",0
LT_SHIFT DB "Left Shift ",0
SHIFT_COMBOS LABEL BYTE
DB CTRL_KEY + RIGHT_SHIFT, CTRL_KEY + LEFT_SHIFT, ALT_KEY + RIGHT_SHIFT
DB ALT_KEY + LEFT_SHIFT, RIGHT_SHIFT + LEFT_SHIFT, CTRL_KEY + ALT_KEY
COMBOS_LEN EQU $ - SHIFT_COMBOS
SHIFT_KEY DB ?
SHIFT_INDEX DW ?
HOTKEY LABEL WORD
SCAN_TEXT DB ?
SCAN_KEY DB ?
HOTKEY_MENU: MOV SI,OFFSET HOT_MENU3
CMP SCAN_ADDR,INACTIVE
JZ DISP_HOT_M
MOV SI,OFFSET HOT_MENU4
DISP_HOT_M: CALL DISPLAY_MENU
MOV AX,HOT_TOP
CALL CALC_ADDR
ADD DI,SELECT_START
MOV BP,DI
MOV BH,COLOR.W
MOV SI,OFFSET HOT_MENU
CALL WRITE_STRING
MOV SI,SHIFT_ADDR
PUSH DS
MOV DS,PGM_BUFF_SEG
MOV AL,[SI] ;Shift key
MOV SI,CS:SCAN_ADDR
MOV AH,[SI] ;AlphaNumeric key
POP DS
MOV SHIFT_KEY,AL
CMP SI,INACTIVE
JNZ SHIFT_ALPHA
SHIFT_ONLY: CALL DISP_COMBOS
ADD BP,CRT_WIDTH
MOV DI,BP
MOV SI,OFFSET HOT_MENU2
CALL WRITE_STRING
ADD BP,CRT_WIDTH
MOV AL,SHIFT_KEY
MOV DI,OFFSET SHIFT_COMBOS
MOV CX,COMBOS_LEN
REPNZ SCASB
NEG CX
ADD CX,COMBOS_LEN - 1
MOV SHIFT_INDEX,CX
;--------------;
NEXT_SH_ONLY: MOV DI,BP
XOR SI,SI
NEXT_SH_ONLY2: MOV AL,SHIFT_COMBOS[SI]
MOV BH,COLOR.C
CMP AL,SHIFT_KEY
JZ DISP_SHIFT
MOV BH,COLOR.W
DISP_SHIFT: PUSH SI
PUSH DI
CALL DISP_COMBOS
POP DI
POP SI
ADD DI,CRT_WIDTH
INC SI
CMP SI,COMBOS_LEN
JB NEXT_SH_ONLY2
CALL SHIFT_HOT
JNC NEXT_SH_ONLY
JMP HOT_DONE1
;--------------;
SHIFT_ALPHA: CALL DISP_COMBOS
XCHG AH,AL
CALL SCAN_LOOKUP
CALL WRITE_SCREEN
ADD BP,CRT_WIDTH
MOV DI,BP
MOV SI,OFFSET HOT_MENU2
CALL WRITE_STRING
ADD BP,CRT_WIDTH
NEXT_S_ALPHA: MOV DI,BP
MOV SI,OFFSET CTRL
MOV BH,COLOR.C
CMP SHIFT_KEY,CTRL_KEY
JZ DISP_CTRL
MOV BH,COLOR.W
DISP_CTRL: CALL WRITE_STRING
MOV DI,BP
ADD DI,CRT_WIDTH
MOV SI,OFFSET ALT
MOV BH,COLOR.C
CMP SHIFT_KEY,ALT_KEY
JZ DISP_ALT
MOV BH,COLOR.W
DISP_ALT: CALL WRITE_STRING
NEXT_S_ALPHA2: CALL GETKEY
JC HOT_DONE1
CMP AL,LEFT_SCAN
JZ HOT_DONE1
CMP AH,CR
JZ HOT_ALPHA
CMP AL,UP_SCAN
JNZ CK_ALPHA_DN
MOV SHIFT_KEY,CTRL_KEY
JMP NEXT_S_ALPHA
CK_ALPHA_DN: CMP AL,DOWN_SCAN
JNZ NEXT_S_ALPHA2
MOV SHIFT_KEY,ALT_KEY
JMP NEXT_S_ALPHA
;--------------;
HOT_ALPHA: MOV SI,OFFSET HOT_MENU5
CALL DISPLAY_MENU
MOV DH,HOT_TOP + 4
MOV DL,SELECT_START SHR 1
CALL SET_CURSOR
ADD BP,CRT_WIDTH
ADD BP,CRT_WIDTH
NEXT_ALPHA: CALL GETKEY
JC HOT_DONE1
CMP AL,LEFT_SCAN
JZ HOT_DONE1
CALL SCAN_LOOKUP
JCXZ NEXT_ALPHA
MOV HOTKEY,AX
MOV DI,BP
MOV BH,COLOR.C
CALL WRITE_SCREEN
MOV MODIFY_FLAG,1
HOT_DONE1: CALL HIDE_CURSOR
CALL CK_MODIFIED
JC HOT_DONE
CALL COPY_HOT
CALL SAVE
HOT_DONE: RET
;--------------;
SCAN_LOOKUP: PUSH ES
PUSH DI
MOV CX,CS
MOV ES,CX
MOV DI,OFFSET SCAN_CODES + 1
MOV CX,SCAN_COUNT ;38 possible Alt key combos.
NEXT_SCAN2: SCASB ;Do we have a match?
JZ GOT_HOT
INC DI ;If no, bump pointer to next byte.
LOOP NEXT_SCAN2
GOT_HOT: MOV AH,AL
MOV AL,[DI - 2]
POP DI
POP ES
RET
;----------------------------------------------;
;INPUT: AL=shift state; DI->screen; BH=color
DISP_COMBOS: PUSH AX
MOV CX,AX
MOV SI,OFFSET CTRL
TEST AL,CTRL_KEY
JZ CK_ALT
CALL WRITE_STRING
CK_ALT: MOV SI,OFFSET ALT
TEST CL,ALT_KEY
JZ CK_RT_SHIFT
CALL WRITE_STRING
CK_RT_SHIFT: MOV SI,OFFSET RT_SHIFT
TEST CL,RIGHT_SHIFT
JZ CK_LF_SHIFT
CALL WRITE_STRING
CK_LF_SHIFT: MOV SI,OFFSET LT_SHIFT
TEST CL,LEFT_SHIFT
JZ SHIFT_DONE
CALL WRITE_STRING
SHIFT_DONE: POP AX
RET
;----------------------------------------------;
SHIFT_HOT: CALL GETKEY
JC SHIFT_HOT_END
CMP AH,CR
JZ SHIFT_ENTER
MOV BL,SHIFT_KEY
MOV SI,SHIFT_INDEX
CMP AL,UP_SCAN
JNZ CK_SHIFT_DN
SUB SI,1
JC SHIFT_HOT
JMP SHORT SHIFT_UPDATE
CK_SHIFT_DN: CMP AL,DOWN_SCAN
JNZ SHIFT_HOT
ADD SI,1
CMP SI,COMBOS_LEN
JZ SHIFT_HOT
SHIFT_UPDATE: MOV AL,SHIFT_COMBOS[SI]
MOV SHIFT_KEY,AL
MOV SHIFT_INDEX,SI
CLC
JMP SHORT SHIFT_HOT_END
SHIFT_ENTER: MOV MODIFY_FLAG,1
STC
SHIFT_HOT_END: RET
;----------------------------------------------;
COPY_HOT: PUSH ES
MOV AL,SHIFT_KEY
MOV DI,OFFSET SHIFT_COMBOS
MOV CX,COMBOS_LEN
REPNZ SCASB
NEG CX
ADD CX,COMBOS_LEN - 1
SHL CX,1
SHL CX,1
ADD CX,OFFSET SHIFT_TEXT
MOV BP,CX
MOV ES,PGM_BUFF_SEG
MOV DI,SHIFT_ADDR
STOSB
MOV DI,SHIFT_TEXT_ADDR
CMP DI,INACTIVE
JZ COPY_SCAN
MOV SI,BP
CMP SCAN_ADDR,INACTIVE
JZ COPY_S_TEXT
MOV SI,OFFSET CTRL
CMP AL,CTRL_KEY
JZ COPY_S_TEXT
MOV SI,OFFSET ALT
COPY_S_TEXT: MOV CX,4
REP MOVSB
COPY_SCAN: MOV DI,SCAN_ADDR
CMP DI,INACTIVE
JZ COPY_H_END
MOV AL,SCAN_KEY
STOSB
MOV DI,SCAN_TEXT_ADDR
CMP DI,INACTIVE
JZ COPY_H_END
MOV AL,SCAN_TEXT
STOSB
COPY_H_END: POP ES
RET
;--------------;
COM_MENU LABEL BYTE
DB "Enter 1, 2 or 3 for COM port. Esc to cancel",0
COM_MENU2 LABEL BYTE
DB "COM port: ",0
COM_MENU3 LABEL BYTE
DB " COM address: ",0
COM_MENU4 LABEL BYTE
DB "Enter desired COM hexadecimal port address from your modem manual. Esc to cancel",0
COM_PORT DW ?
PORT_SCREEN DW ? ;Screen address to write port #
ADDR_SCREEN DW ? ;Screen address to write port addr.
COM_EDIT DB 4 DUP (SPACE)
COM_EDIT_LEN EQU $ - COM_EDIT
DB 0
MODEM_MENU: MOV SI,OFFSET COM_MENU
CALL DISPLAY_MENU
MOV SI,COM_ADDR
PUSH DS
MOV DS,PGM_BUFF_SEG
MOV CX,[SI]
POP DS
MOV COM_PORT,CX
MOV AX,COM_TOP
CALL CALC_ADDR
ADD DI,SELECT_START
MOV BH,COLOR.W
MOV SI,OFFSET COM_MENU2
CALL WRITE_STRING
MOV PORT_SCREEN,DI
MOV AL,"1"
CMP CX,3F8H
JZ DISP_PORT
INC AL
CMP CX,2F8H
JZ DISP_PORT
INC AL
DISP_PORT: MOV BH,COLOR.C
CALL WRITE_SCREEN
MOV BH,COLOR.W
MOV SI,OFFSET COM_MENU3
CALL WRITE_STRING
MOV ADDR_SCREEN,DI
MOV BP,CX
MOV BH,COLOR.C
CALL HEX_ASCII
MOV DH,COM_TOP
MOV DL,SELECT_START SHR 1 +10
CALL SET_CURSOR
NEXT_MODEM: CALL GETKEY
JC M_END1
CMP AH,CR
JZ M_END1
CMP AL,LEFT_SCAN
JZ M_END1
CMP AH,"1"
JB NEXT_MODEM
CMP AH,"3"
JA NEXT_MODEM
MOV AL,AH
MOV CL,AL
MOV DI,PORT_SCREEN
MOV BH,COLOR.C
CALL WRITE_SCREEN
MOV AX,3F8H
CMP CL,"1"
JZ GOT_ADDR
MOV AX,2F8H
CMP CL,"2"
JZ GOT_ADDR
MOV SI,OFFSET COM_MENU4
CALL DISPLAY_MENU
MOV AX,ADDR_SCREEN
MOV SCREEN_START,AX
MOV LINE_START,OFFSET COM_EDIT
MOV LINE_END,OFFSET COM_EDIT + COM_EDIT_LEN
MOV BH,COLOR.C
MOV LEGAL_CHARS,OFFSET NUMBER_CHARS
CALL EDITOR
JC M_END1
CALL CK_HEX
MOV SI,OFFSET COM_EDIT
CALL PARSE_LINE
CALL GET_NUMBER
JC MODEM_ERR
GOT_ADDR: MOV COM_PORT,AX
MOV BP,AX
MOV DI,ADDR_SCREEN
MOV BH,COLOR.C
CALL HEX_ASCII
MOV MODIFY_FLAG,TRUE
M_END1: CALL HIDE_CURSOR
CALL CK_MODIFIED
JC M_END
PUSH ES
MOV ES,PGM_BUFF_SEG
MOV DI,COM_ADDR
MOV AX,COM_PORT
STOSW
POP ES
CALL SAVE
M_END: RET
MODEM_ERR: MOV SI,OFFSET NUMBER_ERR
CALL BACKUP_ERR2
JMP M_END
;--------------;
CK_HEX: MOV SI,OFFSET COM_EDIT
MOV CX,COM_EDIT_LEN
NEXT_CK_HEX: LODSB
CMP AL,SPACE
JBE FOUND_HEX
LOOP NEXT_CK_HEX
DEC SI
MOV DI,SI
MOV AH,[DI]
JMP SHORT FOUND_HEX2
FOUND_HEX: DEC SI
CMP SI,OFFSET COM_EDIT
JBE CK_HEX_END
MOV DI,SI
MOV AH,[DI-1]
FOUND_HEX2: AND AH,5FH
MOV AL,"H"
CMP AH,AL
JZ CK_HEX_END
STOSB
CK_HEX_END: RET
;-----------------------
;INPUT: BP=number; BH=color.
HEX_ASCII: MOV CH,SPACE
MOV AX,BP
MOV AX,BP
XCHG AH,AL
AND AL,0FH
CALL DISP_HEX
MOV AX,BP
MOV CL,4
SHR AL,CL
CALL DISP_HEX
MOV AX,BP
AND AL,0FH
CALL DISP_HEX
MOV AL,"H"
CALL WRITE_SCREEN
RET
;--------------;
DISP_HEX: ADD AL,90H
DAA
ADC AL,40H
DAA
CMP AL,"0"
JZ ADJUST_HEX
MOV CH,"0"
JMP SHORT PRINT_HEX
ADJUST_HEX: MOV AL,CH
PRINT_HEX: CALL WRITE_SCREEN
RET
;--------------;
LPT_MENU LABEL BYTE
DB " printer addresses found. Select printer 1"
LPT_LENGTH EQU $ - LPT_MENU + 1
DB " Esc to cancel",0
PRINTER DB "LPT: ",0
PRINTER_LEN EQU $ - PRINTER
PRINTER_CNT DB ?
PRINTER_MENU: CALL COUNT_PRINTERS
CALL MENU_OFFSET
MOV BH,COLOR.B
PUSH DI
MOV AL,PRINTER_CNT
CALL WRITE_SCREEN
MOV SI,OFFSET LPT_MENU
CALL WRITE_STRING
POP DI
CMP PRINTER_CNT,"1"
JBE GO_PRINTER
ADD DI,LPT_LENGTH * 2
MOV AL,"-"
CALL WRITE_SCREEN
MOV AL,PRINTER_CNT
CALL WRITE_SCREEN
GO_PRINTER: MOV AX,LPT_TOP
CALL CALC_ADDR
ADD DI,SELECT_START
MOV SI,OFFSET PRINTER
MOV BH,COLOR.W
CALL WRITE_STRING
MOV CX,DI
MOV SI,LPT_ADDR
PUSH DS
MOV DS,PGM_BUFF_SEG
MOV AL,[SI]
POP DS
ADD AL,"1"
MOV BH,COLOR.C
CALL WRITE_SCREEN
MOV DH,LPT_TOP
MOV DL,SELECT_START SHR 1 + PRINTER_LEN - 1
CALL SET_CURSOR
NEXT_PRINTER: CALL GETKEY
JC P_END1
XCHG AH,AL
CMP AL,CR
JZ P_END1
CMP AH,LEFT_SCAN
JZ P_END1
CMP AL,"1"
JB NEXT_PRINTER
CMP AL,PRINTER_CNT
JA NEXT_PRINTER
GOT_PRINTER: MOV MODIFY_FLAG,1
MOV DI,CX
MOV BP,AX
CALL WRITE_SCREEN
P_END1: CALL HIDE_CURSOR
CALL CK_MODIFIED
JC P_END
MOV AX,BP
SUB AL,"1"
PUSH ES
MOV ES,PGM_BUFF_SEG
MOV DI,LPT_ADDR
STOSB
POP ES
CALL SAVE
P_END: RET
;--------------;
PRINTER_BASE EQU 8
COUNT_PRINTERS:PUSH DS
MOV AX,40H
MOV DS,AX
MOV AL,"0"
MOV SI,PRINTER_BASE
MOV AH,3
NEXT_PRINTERS: CMP WORD PTR [SI],0
JZ PRINTERS_END
INC SI
INC SI
INC AL
DEC AH
JNZ NEXT_PRINTERS
PRINTERS_END: POP DS
MOV PRINTER_CNT,AL
RET
;--------------;
T_MENU LABEL BYTE
DB "Select text description then press Enter to change text. Esc to Exit",0
TEXT_M DB "Text descriptions",0
DB "~~~~~~~~~~~~~~~~~",0
TEXT_INDEX DW 0
TEXT_MENU: CMP [TEXT_MENUS],INACTIVE
JZ T_MENU_END1
CALL TEXT_DEFAULT
MOV TEXT_INDEX,0
NEXT_T_MENU: MOV STATE,CUSTOM_TYPE
MOV SI,OFFSET T_MENU
CALL DISPLAY_MENU
NEXT_T_MENU2: CALL DISP_TEXT
CALL GETKEY
JC T_MENU_END
CMP AL,LEFT_SCAN
JZ T_MENU_END
CMP AH,CR
JZ DO_TEXT
CMP AL,RIGHT_SCAN
JZ DO_TEXT
CK_T_UP: MOV BX,TEXT_INDEX
CMP AL,UP_SCAN
JNZ CK_T_DN
SUB BX,2
JC NEXT_T_MENU2
JMP SHORT TEXT_UPDATE
CK_T_DN: CMP AL,DOWN_SCAN
JNZ NEXT_T_MENU2
INC BX
INC BX
CMP BX,TEXT_MAX * 2
JAE NEXT_T_MENU2
CMP TEXT_MENUS[BX],INACTIVE
JZ NEXT_T_MENU2
TEXT_UPDATE: MOV TEXT_INDEX,BX
JMP NEXT_T_MENU2
DO_TEXT: CALL TEXT_SELECT
JMP NEXT_T_MENU
T_MENU_END1: CALL BEEP
T_MENU_END: CALL CK_MODIFIED
JC T_M_END
CALL COPY_TEXT
CALL SAVE
T_M_END: RET
;--------------;
TEXT_DEFAULT: PUSH DS
MOV DS,PGM_BUFF_SEG
XOR BX,BX
XOR BP,BP
NEXT_T_DEFAULT:CMP CS:[TEXT_MENUS.BX],INACTIVE
JZ T_DEFAULT_END
MOV SI,CS:[TEXT_ADDRS.BX]
MOV DI,OFFSET TEXT_EDIT
ADD DI,BP
MOV CX,CS:[TEXT_LENGTH.BX]
CMP CX,STRING_MAX
JB GET_DEF
MOV CX,STRING_MAX - 1
GET_DEF: REP MOVSB
XOR AL,AL
STOSB
ADD BP,STRING_MAX
INC BX
INC BX
CMP BX,TEXT_MAX * 2
JB NEXT_T_DEFAULT
T_DEFAULT_END: POP DS
RET
;--------------;
T_EDIT_ADDR DW ?
DISP_TEXT: MOV AX,TEXT_TOP
CALL CALC_ADDR
ADD DI,SELECT_START
MOV BH,COLOR.W
PUSH DI
MOV SI,OFFSET TEXT_M
CALL WRITE_STRING
POP DI
ADD DI,CRT_WIDTH
PUSH DI
CALL WRITE_STRING
POP DI
;--------------;
XOR BP,BP
MOV T_EDIT_ADDR,OFFSET TEXT_EDIT
NEXT_TEXT_DES: MOV SI,TEXT_MENUS[BP]
CMP SI,INACTIVE
JZ TEXT_DES_END
ADD DI,CRT_WIDTH
PUSH DI
MOV CX,STRING_MAX
MOV BH,COLOR.W
CMP TEXT_INDEX,BP
JNZ WRITE_DESC2
MOV BH,COLOR.C
CMP STATE,CUSTOM_TYPE
JZ WRITE_DESC2
MOV BH,COLOR.A
WRITE_DESC2: PUSH DS
MOV DS,ZIF_BUFF_SEG
CALL WRITE_LINE
CALL PAD_LINE
POP DS
MOV BH,COLOR.W
MOV SI,T_EDIT_ADDR
MOV CX,TEXT_LENGTH[BP]
CALL WRITE_LINE
POP DI
ADD T_EDIT_ADDR,STRING_MAX
INC BP
INC BP
CMP BP,TEXT_MAX * 2
JB NEXT_TEXT_DES
TEXT_DES_END: RET
;----------------------------------------------;
TEXT_M2 LABEL BYTE
DB "Edit text then press Enter. Esc to cancel",0
TEXT_SELECT: MOV STATE,SELECT_TYPE
CALL DISP_TEXT
MOV SI,OFFSET TEXT_M2
CALL DISPLAY_MENU
MOV AX,TEXT_INDEX
MOV BX,AX
MOV CX,TEXT_LENGTH[BX]
SHR AX,1
ADD AX,TEXT_TOP + 2
MUL CRT_WIDTH
ADD AX,SELECT_START + (STRING_MAX * 2)
MOV SCREEN_START,AX
MOV AX,STRING_MAX
SHR BX,1
MUL BX
ADD AX,OFFSET TEXT_EDIT
MOV LINE_START,AX
ADD AX,CX
MOV LINE_END,AX
MOV BH,COLOR.C
MOV LEGAL_CHARS,OFFSET ALL_CHARS
CALL EDITOR
JC TEXT_S_END
MOV MODIFY_FLAG,TRUE
TEXT_S_END: RET
;----------------------------------------------;
COPY_TEXT: PUSH ES
MOV ES,PGM_BUFF_SEG
XOR BX,BX
MOV BP,OFFSET TEXT_EDIT
NEXT_T_COPY: CMP TEXT_MENUS[BX],INACTIVE
JZ COPY_T_END
MOV SI,BP
MOV DI,TEXT_ADDRS[BX]
MOV CX,TEXT_LENGTH[BX]
REP MOVSB
INC BX
INC BX
ADD BP,STRING_MAX
JMP NEXT_T_COPY
COPY_T_END: POP ES
RET
;--------------;
N_MENU LABEL BYTE
DB "Select number description then press Enter to change number. Esc to Exit",0
NUMBER_M DB "Number descriptions",0
DB "~~~~~~~~~~~~~~~~~~~",0
NUMBER_INDEX DW 0
NUMBER_MENU: CMP [NUMBER_MENUS],INACTIVE
JZ N_MENU_END1
CALL NUM_DEFAULT
MOV NUMBER_INDEX,0
NEXT_N_MENU: MOV STATE,CUSTOM_TYPE
MOV SI,OFFSET N_MENU
CALL DISPLAY_MENU
NEXT_N_MENU2: CALL DISP_NUMBERS
CALL GETKEY
JC N_MENU_END
CMP AL,LEFT_SCAN
JZ N_MENU_END
CMP AH,CR
JZ DO_NUM
CMP AL,RIGHT_SCAN
JZ DO_NUM
CK_N_UP: MOV BX,NUMBER_INDEX
CMP AL,UP_SCAN
JNZ CK_N_DN
SUB BX,2
JC NEXT_N_MENU2
JMP SHORT NUM_UPDATE
CK_N_DN: CMP AL,DOWN_SCAN
JNZ NEXT_N_MENU2
INC BX
INC BX
CMP BX,NUM_MAX * 2
JAE NEXT_N_MENU2
CMP NUMBER_MENUS[BX],INACTIVE
JZ NEXT_N_MENU2
NUM_UPDATE: MOV NUMBER_INDEX,BX
JMP NEXT_N_MENU2
DO_NUM: CALL NUMBER_SELECT
JMP NEXT_N_MENU
N_MENU_END1: CALL BEEP
N_MENU_END: CALL CK_MODIFIED
JC N_M_END
CALL COPY_NUMBERS
CALL SAVE
N_M_END: RET
;----------------------------------------------;
NUM_DEFAULT: PUSH DS
MOV DS,PGM_BUFF_SEG
XOR BX,BX
MOV BP,OFFSET NUMBER_EDIT
NEXT_N_DEFAULT:CMP CS:[NUMBER_MENUS.BX],INACTIVE
JZ N_DEFAULT_END
MOV SI,CS:[NUMBER_ADDRS.BX]
MOV AX,[SI]
CMP BYTE PTR CS:[NUMBER_TYPE.BX],"W"
JZ GOT_NUM_VAL
XOR AH,AH
GOT_NUM_VAL: MOV DI,BP
CALL DECIMAL_ASCII
ADD BP,INTEGER_MAX
INC BX
INC BX
CMP BX,NUM_MAX * 2
JB NEXT_N_DEFAULT
N_DEFAULT_END: POP DS
RET
;----------------------------------------------;
DECIMAL_ASCII: PUSH BX
MOV BX,10 ;Divisor of ten.
XOR CX,CX ;Zero in counter.
NEXT_COUNT: XOR DX,DX ;Zero in high half.
DIV BX ;Divide by ten.
ADD DL,"0" ;Convert to ASCII.
PUSH DX ;Save results.
INC CX ;Also increment count.
OR AX,AX ;Are we done?
JNZ NEXT_COUNT ;Continue until zero.
MOV SI,INTEGER_MAX - 1
SUB SI,CX
NEXT_DEC_STORE:POP AX ;Retrieve numbers.
STOSB
LOOP NEXT_DEC_STORE
MOV CX,SI
JCXZ DEC_END
MOV AL,SPACE
REP STOSB
DEC_END: XOR AL,AL
STOSB
POP BX
RET
;----------------------------------------------;
N_EDIT_ADDR DW ?
DISP_NUMBERS: MOV AX,NUMBER_TOP
CALL CALC_ADDR
ADD DI,SELECT_START
MOV BH,COLOR.W
PUSH DI
MOV SI,OFFSET NUMBER_M
CALL WRITE_STRING
POP DI
ADD DI,CRT_WIDTH
PUSH DI
CALL WRITE_STRING
POP DI
;--------------;
XOR BP,BP
MOV N_EDIT_ADDR,OFFSET NUMBER_EDIT
NEXT_NUM_DES: MOV SI,NUMBER_MENUS[BP]
CMP SI,INACTIVE
JZ NUM_DES_END
ADD DI,CRT_WIDTH
PUSH DI
MOV BH,COLOR.W
CMP NUMBER_INDEX,BP
JNZ WRITE_DESC3
MOV BH,COLOR.C
CMP STATE,CUSTOM_TYPE
JZ WRITE_DESC3
MOV BH,COLOR.A
WRITE_DESC3: PUSH DS
MOV DS,ZIF_BUFF_SEG
MOV CX,STRING_MAX
CALL WRITE_LINE
CALL PAD_LINE
POP DS
MOV BH,COLOR.W
MOV SI,N_EDIT_ADDR
CALL WRITE_STRING
POP DI
ADD N_EDIT_ADDR,INTEGER_MAX
INC BP
INC BP
CMP BP,NUM_MAX * 2
JB NEXT_NUM_DES
NUM_DES_END: RET
;----------------------------------------------;
NUMBER_M2 LABEL BYTE
DB "Enter number between "
RANGE_L EQU $ - NUMBER_M2
DB " Esc to cancel",0
NUMBER_SELECT: MOV STATE,SELECT_TYPE
CALL DISP_NUMBERS
CALL MENU_OFFSET
MOV BH,COLOR.B
PUSH DI
MOV SI,OFFSET NUMBER_M2
CALL WRITE_STRING
MOV BP,NUMBER_INDEX
MOV AX,RANGE_LOW[BP]
MOV DI,OFFSET NUMBER_RANGE
CALL DECIMAL_ASCII
POP DI
ADD DI,RANGE_L * 2
MOV SI,OFFSET NUMBER_RANGE
NEXT_RANGE: LODSB
CMP AL,SPACE
JA NEXT_RANGE
MOV BYTE PTR [SI-1],0
MOV SI,OFFSET NUMBER_RANGE
CALL WRITE_STRING
MOV AL,"-"
CALL WRITE_SCREEN
PUSH DI
MOV AX,RANGE_HIGH[BP]
MOV DI,OFFSET NUMBER_RANGE
CALL DECIMAL_ASCII
POP DI
MOV SI,OFFSET NUMBER_RANGE
CALL WRITE_STRING
MOV AX,NUMBER_INDEX
MOV BX,AX
SHR AX,1
ADD AX,NUMBER_TOP + 2
MUL CRT_WIDTH
ADD AX,SELECT_START + (STRING_MAX * 2)
MOV SCREEN_START,AX
MOV AX,INTEGER_MAX
SHR BX,1
MUL BX
ADD AX,OFFSET NUMBER_EDIT
MOV LINE_START,AX
ADD AX,INTEGER_MAX - 1
MOV LINE_END,AX
MOV BH,COLOR.C
MOV LEGAL_CHARS,OFFSET NUMBER_CHARS
CALL EDITOR
JC NUM_S_END
MOV SI,LINE_START
CALL PARSE_LINE
JC NUM_S_END2
CALL GET_NUMBER
JC NUMBER_ERROR
MOV BP,NUMBER_INDEX
CMP AX,RANGE_LOW[BP]
JB NUMBER_ERROR
CMP AX,RANGE_HIGH[BP]
JA NUMBER_ERROR
NUM_S_END2: MOV MODIFY_FLAG,TRUE
NUM_S_END: RET
NUMBER_ERROR: MOV SI,OFFSET NUMBER_ERR
CALL BACKUP_ERR2
PUSH DS
MOV BX,NUMBER_INDEX
MOV SI,DS:[NUMBER_ADDRS.BX]
MOV DS,PGM_BUFF_SEG
MOV AX,[SI]
POP DS
CMP BYTE PTR [NUMBER_TYPE.BX],"W"
JZ RESTORE_NUM
XOR AH,AH
RESTORE_NUM: MOV DI,LINE_START
CALL DECIMAL_ASCII
JMP NUM_S_END
;----------------------------------------------;
COPY_NUMBERS: PUSH ES
MOV ES,PGM_BUFF_SEG
XOR BX,BX
MOV BP,OFFSET NUMBER_EDIT
NEXT_N_COPY: CMP NUMBER_MENUS[BX],INACTIVE
JZ COPY_N_END
MOV SI,BP
CALL PARSE_LINE
JC LOOP_N_COPY
CALL GET_NUMBER
JC LOOP_N_COPY
MOV DI,NUMBER_ADDRS[BX]
CMP BYTE PTR NUMBER_TYPE[BX],"W"
JZ COPY_WORD
STOSB
JMP SHORT LOOP_N_COPY
COPY_WORD: STOSW
LOOP_N_COPY: INC BX
INC BX
ADD BP,INTEGER_MAX
JMP NEXT_N_COPY
COPY_N_END: POP ES
RET
;----------------------------------------------;
DISP_CUSTOM: MOV AX,LISTING_TOP
CALL CALC_ADDR
ADD DI,CUSTOM_START
MOV SI,OFFSET CATEGORY + SIZE CAT
MOV BP,LISTING_LEN
NEXT_CUSTOM: PUSH SI
PUSH DI
MOV CX,CRT_WIDTH
SUB CX,CUSTOM_START
SHR CX,1
CMP SI,OFFSET CAT_END
JAE PAD_CUSTOM
CMP [SI.CAT_STATUS],INACTIVE
JZ GET_INACTIVE
CMP SI,CUSTOM_ADDR
JNZ CK_CUST_COLOR
MOV BH,COLOR.C
CMP STATE,FILE_TYPE
JZ DISPLAY_CUST
MOV BH,COLOR.A
JMP SHORT DISPLAY_CUST
CK_CUST_COLOR: MOV BH,COLOR.I
CMP STATE,LISTING_TYPE
JNZ DISPLAY_CUST
MOV BH,COLOR.W
JMP SHORT DISPLAY_CUST
GET_INACTIVE: MOV BH,COLOR.T
CMP SI,CUSTOM_ADDR
JZ DISPLAY_CUST
MOV BH,COLOR.S
DISPLAY_CUST: ADD SI,SIZE CAT_STATUS + SIZE CAT_LEN
MOV AL,"["
CALL WRITE_CHAR
DEC CX
CALL WRITE_LINE
MOV BH,COLOR.W
CALL PAD_LINE
CK_LAST_CUST: POP DI
POP SI
ADD DI,CRT_WIDTH
CMP SI,OFFSET CAT_END
JAE LOOP_CUST
ADD SI,SIZE CAT
LOOP_CUST: DEC BP
JNZ NEXT_CUSTOM
RET
PAD_CUSTOM: MOV BH,COLOR.W
CALL PAD_LINE
JMP SHORT CK_LAST_CUST
;----------------------------------------------;
TOP_WINDOW LABEL BYTE
DB "╔════════════════════════════════════════╗",0
WINDOW_LEN EQU $ - TOP_WINDOW
BOTTOM_WINDOW LABEL BYTE
DB "╚════════════════════════════════════════╝",0
MODIFY_MENU LABEL BYTE
DB "║ Do you wish to save your changes? Y/N ║",0
BACKUP_MENU LABEL BYTE
DB "║ Backup up program first? Y/N ║",0
OVERWRITE_MENU LABEL BYTE
DB "║ Backup file exists. Overwrite? Y/N ║",0
DISK_FULL_MENU LABEL BYTE
DB "║ Not enough disk space. Press any key. ║",0
BACKUP_FAIL LABEL BYTE
DB "║ Backup failed. Press any key. ║",0
SAVE_FAIL LABEL BYTE
DB "║ Save failed. Press any key. ║",0
NUMBER_ERR LABEL BYTE
DB "║ Number out of range. Press any key. ║",0
CK_MODIFIED: CMP MODIFY_FLAG,TRUE
JNZ NO_MODIFY
MOV MODIFY_FLAG,FALSE
NEXT_MODIFY: MOV SI,OFFSET MODIFY_MENU
CALL DISP_WINDOW
CALL CLEAR_KEY
CALL GETKEY
CMP AL,ESC_SCAN
JZ NO_MODIFY
CMP AL,N_SCAN
JZ NO_MODIFY
CMP AL,Y_SCAN
JNZ NEXT_MODIFY
CK_BACKUP: CMP BACKUP_FLAG,TRUE
JZ YES_MODIFY
MOV SI,OFFSET BACKUP_MENU
CALL DISP_WINDOW
CALL CLEAR_KEY
GET_MODIFY: CALL GETKEY
CMP AL,ESC_SCAN
JZ NO_MODIFY
CMP AL,N_SCAN
JZ YES_MODIFY
CMP AL,Y_SCAN
JNZ GET_MODIFY
CALL DO_BACKUP
JC NEXT_MODIFY
YES_MODIFY: CALL CLEAR_MODIFIED
CLC
JMP SHORT MODIFIED_END
NO_MODIFY: CALL CLEAR_MODIFIED
STC
MODIFIED_END: RET
;----------------------------------------------;
; OUTPUT: CF=1 if failed.
READ_HANDLE DW ?
WRITE_HANDLE DW ?
DO_BACKUP: CALL MAKE_BACKUP
MOV DX,OFFSET BACKUP_NAME
XOR CX,CX
MOV AH,4EH
INT 21H
JNC OVERWRITE
CALL GET_FREE
JNC FREE_SPACE2
JMP BACKUP_END
OVERWRITE: MOV SI,OFFSET OVERWRITE_MENU
CALL DISP_WINDOW
CALL CLEAR_KEY
CALL GETKEY
CMP AL,Y_SCAN
JZ GET_DISK
CMP AL,ESC_SCAN
JNZ CK_OVER2
STC
JMP BACKUP_END2
CK_OVER2: CMP AL,N_SCAN
JNZ OVERWRITE
JMP BACKUP_END
GET_DISK: CALL GET_FREE
JNC FREE_SPACE
JMP BACKUP_ERR
FREE_SPACE: ADD AX,DTA.SIZE_LOW
ADC DX,DTA.SIZE_HIGH
FREE_SPACE2: SUB AX,FILE_SIZE[0]
SBB DX,FILE_SIZE[2]
JNC CREATE
MOV SI,OFFSET DISK_FULL_MENU
JMP SHORT BACKUP_ERR2
CREATE: MOV DX,OFFSET BACKUP_NAME
XOR CX,CX
MOV AH,3CH
INT 21H
JNC DO_BACKUP2
JMP SHORT BACKUP_ERR
DO_BACKUP2: MOV WRITE_HANDLE,AX
MOV DX,OFFSET ASCIIZ_NAME
MOV AX,3D00H
INT 21H
JC CLOSE_READ
MOV READ_HANDLE,AX
XOR DX,DX
NEXT_BACKUP: MOV BX,READ_HANDLE
MOV CX,BAC_BUFF_SIZE * KILOBYTES - 1
PUSH DS
MOV DS,BAC_BUFF_SEG
MOV AH,3FH
INT 21H
POP DS
JC CLOSE_READ
OR AX,AX
JZ CLOSE_READ
MOV CX,AX
MOV BX,WRITE_HANDLE
PUSH DS
MOV DS,BAC_BUFF_SEG
MOV AH,40H
INT 21H
POP DS
JC CLOSE_READ
CMP CX,AX
STC
JNZ CLOSE_READ
CMP CX,BAC_BUFF_SIZE * KILOBYTES - 1
JZ NEXT_BACKUP
CLC
CLOSE_READ: PUSHF
MOV BX,READ_HANDLE
MOV AH,3EH
INT 21H
POPF
CLOSE_WRITE: PUSHF
MOV BX,WRITE_HANDLE
MOV AH,3EH
INT 21H
POPF
JC BACKUP_ERR
BACKUP_END: MOV BACKUP_FLAG,TRUE
CALL CLEAR_MODIFIED
MOV FAIL_FLAG,FALSE
CLC
BACKUP_END2: RET
BACKUP_ERR: MOV SI,OFFSET BACKUP_FAIL
BACKUP_ERR2: CALL DISP_WINDOW
CALL BEEP
CALL GETKEY
CALL CLEAR_MODIFIED
MOV FAIL_FLAG,FALSE
STC
RET
;----------------------------------------------;
GET_FREE: MOV DL,PGM_DRIVE
INC DL
MOV AH,36H ;Disk free space.
INT 21H
CMP AX,-1
STC
JZ DISK_FREE_END
MUL BX ;Sectors per cluster * clusters
PUSH DX
MUL CX ;Result times bytes per cluster
MOV BX,AX
POP AX
PUSH DX
MUL CX
POP DX
ADD DX,AX
MOV AX,BX
CLC
DISK_FREE_END: RET ; = available bytes.
;----------------------------------------------;
BAK DB ".BAK",0
MAKE_BACKUP: MOV SI,OFFSET ASCIIZ_NAME
MOV DI,OFFSET BACKUP_NAME
MOV CX,8
NEXT_BACK: LODSB
CMP AL,"."
JZ BAK_EXT
OR AL,AL
JZ BAK_EXT
STOSB
LOOP NEXT_BACK
BAK_EXT: MOV SI,OFFSET BAK
MOV CX,5
REP MOVSB
RET
;----------------------------------------------;
; INPUT: SI-> window.
DISP_WINDOW: CALL CALC_WIN
MOV BH,COLOR.W
PUSH DI
PUSH SI
MOV SI,OFFSET TOP_WINDOW
CALL WRITE_STRING
POP SI
POP DI
ADD DI,CRT_WIDTH
PUSH DI
CALL WRITE_STRING
POP DI
ADD DI,CRT_WIDTH
MOV SI,OFFSET BOTTOM_WINDOW
CALL WRITE_STRING
RET
;----------------------------------------------;
CLEAR_MODIFIED:CALL CALC_WIN
MOV BH,COLOR.W
MOV AL,SPACE
MOV SI,3
NEXT_CLEAR_M: PUSH DI
MOV CX,WINDOW_LEN
CALL REPEAT_CHAR
POP DI
ADD DI,CRT_WIDTH
DEC SI
JNZ NEXT_CLEAR_M
RET
;----------------------------------------------;
CALC_WIN: MOV AL,ROWS
DEC AL
DEC AL
DEC AL
XOR AH,AH
CALL CALC_ADDR
ADD DI,SELECT_START
RET
;----------------------------------------------;
SAVE: CALL MAKE_FILENAME
MOV DX,OFFSET ASCIIZ_NAME
MOV AX,3D01H
INT 21H
JC SAVE_ERR
CMP FAIL_FLAG,TRUE
JZ SAVE_ERR
MOV BX,AX
MOV CX,PGM_BYTES
XOR DX,DX
PUSH DS
MOV DS,PGM_BUFF_SEG
MOV AH,40H
INT 21H
POP DS
PUSHF
MOV AH,3EH
INT 21H
POPF
JNC SAVE_END
SAVE_ERR: MOV SI,OFFSET SAVE_FAIL
CALL DISP_WINDOW
CALL BEEP
CALL GETKEY
CALL CLEAR_MODIFIED
STC
SAVE_END: MOV FAIL_FLAG,FALSE
RET
;----------------------------------------------;
CLEAR_FILE: PUSH ES
PUSH DI
MOV AX,LISTING_TOP
CALL CALC_ADDR
ADD DI,CUSTOM_START
MOV BP,LISTING_LEN
MOV DX,STATUS_REG ;Retrieve status register.
MOV ES,VIDEO_SEG
MOV BH,COLOR.W
MOV AL,SPACE
NEXT_CLEAR: PUSH DI
MOV CX,CRT_WIDTH
SUB CX,CUSTOM_START
SHR CX,1
NEXT_CLEAR2: CALL WRITE_CHAR
LOOP NEXT_CLEAR2
POP DI
ADD DI,CRT_WIDTH
DEC BP
JNZ NEXT_CLEAR
POP DI
POP ES
RET
;--------------------------------------------------------------;
; OUTPUT: ASCIIZ_NAME = filename
MAKE_ZIF_NAME: PUSH DS
MOV SI,BAR_ADDR
MOV DS,FILENAME_SEG ;DS:SI -> Source name.
MOV DI,OFFSET ASCIIZ_NAME ;Name storage.
MOV CX,8 ;8 characters of name.
NEXT_NAME2: LODSB
CMP AL,SPACE ;End of name?
JZ EXTENSION3 ;If yes, do extension.
STOSB
LOOP NEXT_NAME2
EXTENSION3: POP DS
MOV SI,OFFSET ZIF_EXT
MOV CX,ZIF_LEN
REP MOVSB
RET
;----------------------------------------------;
MAKE_FILENAME: PUSH DS
MOV SI,BAR_ADDR
MOV DS,FILENAME_SEG ;DS:SI -> Source name.
MOV BP,SI
MOV DI,OFFSET ASCIIZ_NAME ;Name storage.
MOV CX,8 ;8 characters of name.
NEXT_NAME: LODSB
CMP AL,SPACE ;End of name?
JZ EXTENSION2 ;If yes, do extension.
STOSB
LOOP NEXT_NAME
EXTENSION2: MOV SI,BP ;Retrieve name start.
ADD SI,9 ;Move to extension field.
CMP BYTE PTR [SI],SPACE ;Is there any extension?
JZ NAME_DONE ;If no, done.
MOV AL,"." ;Else, add delimiting dot.
STOSB
MOV CX,3 ;3 characters for extension.
NEXT_EXT: LODSB
CMP AL,SPACE
JZ NAME_DONE
STOSB
LOOP NEXT_EXT
NAME_DONE: XOR AL,AL ;ASCIIZ.
STOSB
POP DS
RET
;----------------------------------------------;
DISP_LISTING: PUSH DS
PUSH ES
MOV AX,LISTING_TOP
CALL CALC_ADDR
MOV SI,LISTING_ADDR
MOV BP,LISTING_LEN
MOV DX,STATUS_REG ;Retrieve status register.
MOV ES,VIDEO_SEG ;Point to screen segment.
MOV DS,FILENAME_SEG
NEXT_LISTING: PUSH DI
MOV CX,SIZE FILE_RECORD
DISPLAY_LINE: MOV BH,CS:COLOR.I
CMP BYTE PTR [SI],-1
JZ PAD_LISTING
CMP SI,CS:BAR_ADDR
JZ CK_BAR_COLOR
CMP CS:STATE,FILE_TYPE
JNZ DISPLAY_LINE2
MOV BH,CS:COLOR.W
JMP SHORT DISPLAY_LINE2
CK_BAR_COLOR: MOV BH,CS:COLOR.C
CMP CS:STATE,FILE_TYPE
JNZ DISPLAY_LINE2
MOV BH,CS:COLOR.A
DISPLAY_LINE2: LODSB
CALL WRITE_CHAR
LOOP DISPLAY_LINE2
CK_LAST_LINE: POP DI
ADD DI,CS:CRT_WIDTH
DEC BP
JNZ NEXT_LISTING
POP ES
POP DS
RET
PAD_LISTING: CALL PAD_LINE
JMP SHORT CK_LAST_LINE
;--------------;
PAD_LINE: JCXZ PAD_LINE_END
MOV AL,SPACE
PAD_LINE2: CALL WRITE_CHAR
LOOP PAD_LINE2
PAD_LINE_END: RET
;----------------------------------------------;
; Keeps track of a variable length field in CX while writing string.
WRITE_LINE: LODSB
OR AL,AL
JZ WRITE_LINE_END
CALL WRITE_CHAR
LOOP WRITE_LINE
WRITE_LINE_END:RET
;--------------;
DUMMY_RET: RET
;----------------------------------------------;
ZIF_DIR_MENU DB " Zif Directory is ",0
PGM_DIR_MENU DB " Utility Directory is ",0
HEADING DB "Utilities ",0,"Custom Categories",0
DB "~~~~~~~~~ ",0,"~~~~~~~~~~~~~~~~~",0
DISP_DIR: MOV BH,COLOR.B
MOV DI,CRT_WIDTH
MOV CX,DI
SHR CX,1
PUSH DI
MOV SI,OFFSET ZIF_DIR_MENU
CALL WRITE_LINE
MOV AL,ZIF_DRIVE
ADD AL,"A"
CALL WRITE_CHAR
DEC CX
MOV AL,":"
CALL WRITE_CHAR
DEC CX
MOV SI,OFFSET ZIF_DIR
CALL WRITE_LINE
CALL PAD_LINE
POP DI
MOV CX,CRT_WIDTH
ADD DI,CX
PUSH DI
SHR CX,1
MOV SI,OFFSET PGM_DIR_MENU
CALL WRITE_LINE
MOV AL,PGM_DRIVE
ADD AL,"A"
CALL WRITE_CHAR
DEC CX
MOV AL,":"
CALL WRITE_CHAR
DEC CX
MOV SI,OFFSET PGM_DIR
CALL WRITE_LINE
CALL PAD_LINE
POP DI
MOV CX,CRT_WIDTH
ADD DI,CX
SHR CX,1
PUSH DI
MOV BH,COLOR.W
MOV SI,OFFSET HEADING
CALL WRITE_LINE
INC DI
INC DI
DEC CX
CALL WRITE_LINE
CALL PAD_LINE
POP DI
MOV CX,CRT_WIDTH
ADD DI,CX
SHR CX,1
CALL WRITE_LINE
INC DI
INC DI
DEC CX
CALL WRITE_LINE
CALL PAD_LINE
RET
;---------------------------------------------------;
; Insertion sort; Doesn't destroy secondary sorts. ;
;---------------------------------------------------;
SORT: MOV BP,LAST_ADDR
XOR SI,SI ;SI = First record.
MOV DI,SIZE FILE_RECORD ;DI = Second record.
PUSH DS
PUSH ES
MOV ES,FILENAME_SEG
MOV DS,FILENAME_SEG
CMP BYTE PTR [SI],-1
JZ SORT_END
CMP BYTE PTR [DI],-1
JZ SORT_END
NEXT_SORT: CMP DI,BP ;Sort is done when last record.
JA SORT_END
PUSH SI ;Save record pointers.
PUSH DI
MOV AX,SI ;Carry source pointer in AX.
MOV DX,DI ;Carry destination pointer in DX.
NEXT_RECORD: MOV CX,SIZE FILE_RECORD ;Field length.
COMPARE: REPZ CMPSB ;Compare the fields.
JBE NO_SWITCH ;If below or equal, no switch.
SWAP: CMP DX,TEMP_RECORD ;Else, if DX points to temporary
JZ DO_SWAP ; storage, safe to move.
MOV SI,DX ;Else, move destination record
MOV DX,TEMP_RECORD ; to temporary storage.
MOV DI,DX
MOV CX,SIZE FILE_RECORD / 2
REP MOVSW
DO_SWAP: MOV SI,AX ;Restore source pointer
MOV DI,SI ;Destination = source +
ADD DI,SIZE FILE_RECORD ; field size.
MOV CX,SIZE FILE_RECORD / 2
REP MOVSW ;Move the record.
MOV DI,DX ;Prepare for next compare.
SUB AX,SIZE FILE_RECORD ;Destination = temporary.
MOV SI,AX ;Move one record towards start.
JNC NEXT_RECORD
NO_SWITCH: MOV SI,TEMP_RECORD ;If DX doesn't point to temporary
CMP DX,SI ; storage, no move was made; next
JNZ NEXT_INSERT ; compare.
MOV DI,AX ;Else, move temporary record
ADD DI,SIZE FILE_RECORD ; into last move location.
MOV CX,SIZE FILE_RECORD / 2
REP MOVSW
NEXT_INSERT: POP DI ;Restore outside loop pointers.
POP SI
ADD SI,SIZE FILE_RECORD ;Move both source and destination
ADD DI,SIZE FILE_RECORD ; to the next record.
JMP NEXT_SORT
SORT_END: POP ES
POP DS
MOV FILE_CURRENT,FALSE
RET
;----------------------------------------------;
; OUTPUT: CF=1 if illegal parameter; DX-> illegal parameter.
PARSE: MOV SI,81H
MOV DI,OFFSET ZIF_DRIVE
CALL PARSE_IT
CALL RESTORE_DIR
CALL PARSE_DELIMIT
CMP BYTE PTR [SI],SPACE
JA PARSE_PGM
COPY_ZIF: MOV SI,OFFSET ZIF_DRIVE
MOV DI,OFFSET PGM_DRIVE
MOV CX,SPEC_SIZE
REP MOVSB
CLC
JMP SHORT PARSE_END
PARSE_PGM: CMP BYTE PTR [SI],";"
JNZ PARSE_PGM2
INC SI
PARSE_PGM2: MOV DI,OFFSET PGM_DRIVE
CALL PARSE_IT
JC COPY_ZIF
PARSE_END: RET
;----------------------------------------------;
; INPUT: SI-> parameter; DI-> storage.
; OUTPUT: CF=1 if illegal parameter; DX-> illegal parameter; SI-> parameter end.
PARSE_IT: CALL PARSE_DELIMIT
MOV BX,SI ;Filespec start.
NEXT_PARSE: LODSB
CMP AL,";"
JZ PARSE_DRIVE
CMP AL,","
JZ PARSE_DRIVE
CMP AL,"/"
JZ PARSE_DRIVE
CMP AL,SPACE
JBE PARSE_DRIVE
CMP AL,":"
JNZ NEXT_PARSE
MOV DL,[SI-2]
AND DL,5FH ;Capitalize.
SUB DL,"A" ;Convert to DOS format.
CALL SELECT_DISK
MOV BX,SI ;Save as filename start.
JMP NEXT_PARSE ;Continue parsing.
PARSE_DRIVE: MOV AH,19H
INT 21H
STOSB
PUSH SI
MOV SI,OFFSET CURRENT_DIR
CALL GET_DIR
POP SI
DEC SI
CMP SI,BX
JZ PARSE_DIR
PUSH [SI]
MOV BYTE PTR [SI],0
MOV DX,BX
CALL CHANGE_DIR
POP [SI]
PARSE_DIR: PUSHF
PUSH SI
MOV SI,DI
CALL GET_DIR
POP SI
POPF
PARSE_DIR_END: MOV DX,BX
RET
;-----------------------------------------------------------------;
; INPUT: SI -> string; OUTPUT SI -> first non-white space. ;
;-----------------------------------------------------------------;
PARSE_DELIMIT:
NEXT_DELIMIT: LODSB ;Get a byte.
OR AL,AL
JZ LEADING_END2
CMP AL,CR
JZ LEADING_END2
CMP AL,SPACE ;Is it a space char or below?
JBE NEXT_DELIMIT
LEADING_END2: DEC SI ;Else, adjust pointer to
RET ; string start.
;----------------------------------------------;
PARSE_LINES: CALL PARSE_LINE
JNC PARSE_LINE_END
CMP AL,LF
JZ PARSE_LINES
JMP SHORT NO_PARA2
PARSE_LINE: LODSB
CMP AL,CTRL_Z
JZ NO_PARA
CMP AL,"["
JZ NO_PARA
CMP AL,LF
JZ NO_PARA2
CMP AL,SPACE
JBE PARSE_LINE
CMP AL,"="
JZ PARSE_LINE
CMP AL,";"
JZ COMMENTS
CLC
DEC SI
PARSE_LINE_END:RET
COMMENTS: LODSB
CMP AL,CTRL_Z
JZ NO_PARA
CMP AL,LF
JZ NO_PARA2
JMP COMMENTS
NO_PARA: DEC SI
NO_PARA2: STC
RET
;----------------------------------------------;
; INPUT: SI -> ASCII number.
; OUTPUT: CF=1 if no number. CX:AX = number.
NUM_FLAG DB ?
GET_NUMBER: PUSH SI
NEXT_CAP2: LODSB
CMP AL,SPACE
JBE GET_TYPE
CMP AL,"a"
JB NEXT_CAP2
CMP AL,"z"
JA NEXT_CAP2
AND BYTE PTR [SI-1],5FH
JMP NEXT_CAP2
GET_TYPE: POP SI
PUSH SI
NEXT_TYPE: LODSB
CMP AL,SPACE
JBE A_NUMBER
CMP AL,"A"
JB NEXT_TYPE
CMP AL,"H"
JA NEXT_TYPE
POP SI
CALL DO_HEX
JMP SHORT NUMBER_END
A_NUMBER: POP SI
CALL DO_NUMBER
NUMBER_END: RET
;--------------;
DO_HEX: PUSH BX
XOR BX,BX ;Start with zero.
XOR CX,CX
MOV CS:NUM_FLAG,0 ;Number exists flag.
NEXT_HEX: LODSB ;Get a byte.
CMP AL,CTRL_Z
JZ HEX_END1
CMP AL,"H"
JZ HEX_END2
CMP AL,COMMA
JZ NEXT_HEX
CMP AL,"-"
JZ HEX_END2
CMP AL,SPACE
JBE HEX_END2
SUB AL,"0" ;ASCII to binary.
JC HEX_ERR ;If not 0 to 9, skip.
CMP AL,9 ;Is it A - F ?
JLE NOT_ALPHA ;If no, OK.
SUB AL,7 ;Else, adjust for alpha.
CMP AL,10 ;Is it punctuation?
JB HEX_END2 ;If yes, skip.
CMP AL,15 ;Is it valid?
JA HEX_ERR ;If no, skip.
NOT_ALPHA: MOV AH,4
NEXT_SHIFT2: SHL BX,1
RCL CX,1
DEC AH
JNZ NEXT_SHIFT2
OR BL,AL ;Add to number.
MOV CS:NUM_FLAG,1
JMP NEXT_HEX
HEX_END1: DEC SI
HEX_END2: MOV AX,BX
CMP CS:NUM_FLAG,0
JZ HEX_ERR
CLC
HEX_END: POP BX
RET
HEX_ERR: STC
POP BX
RET
;--------------;
DO_NUMBER: PUSH BX
PUSH BP
XOR BX,BX ;Start with zero.
XOR CX,CX
MOV CS:NUM_FLAG,0 ;Number exists flag.
MOV BP,10
NEXT_NUMBER: LODSB
XOR AH,AH ;Zero in high half.
CMP AL,CTRL_Z
JZ NUM_END1
CMP AL,COMMA
JZ NEXT_NUMBER
CMP AL,"-"
JZ NUM_END2
CMP AL,SPACE ;Is byte a carriage return?
JBE NUM_END2 ;If yes, done.
CMP AL,COMMA
JZ NEXT_NUMBER
CMP AL,"0" ;Is byte a number?
JB NUM_ERR
CMP AL,"9"
JA NUM_ERR ;If no, done.
SUB AL,"0" ;Else, convert to hex.
XCHG AX,BX ;Store in BX.
MUL BP ;Multiply accumulated by 10.
PUSH DX
XCHG AX,CX
MUL BP
ADD BX,CX
POP CX
ADC CX,0
ADD CX,AX
MOV CS:NUM_FLAG,1 ;Flag number found.
JMP NEXT_NUMBER
NUM_END1: DEC SI
NUM_END2: MOV AX,BX
CMP CS:NUM_FLAG,0
JZ NUM_ERR
CLC
NUM_END: POP BP
POP BX
RET
NUM_ERR: STC
POP BP
POP BX
RET
;----------------------------------------------;
VIDEO_SETUP: PUSH ES
MOV AX,500H ;Make sure active page is zero.
INT 10H
MOV AX,40H ;Point to the ROM BIOS data area
MOV ES,AX
MOV AX,ES:CRT_COLS
MOV COLUMNS,AX
SHL AX,1
MOV CRT_WIDTH,AX
MOV AX,ES:[4EH]
MOV CRT_START,AX
MOV AX,ES:[63H]
ADD AX,6
MOV CX,0B000H
CMP AX,3BAH
JZ STORE_SEG
ADD CX,800H
STORE_SEG: MOV STATUS_REG,AX
MOV VIDEO_SEG,CX
MOV SI,OFFSET MONO_ATTR
MOV AL,ES:CRT_MODE ;Retrieve current video mode.
CMP AL,7 ;Is it mono mode?
JZ GET_ROWS ;If yes, continue.
CMP AL,2 ;Is it BW80?
JZ GET_ROWS ;If yes, continue.
MOV SI,OFFSET COLOR_ATTR
CMP AL,3 ;Is it mode CO80?
JZ GET_ROWS ;If yes, continue.
MOV AX,3 ;Else, change video mode to CO80.
INT 10H
GET_ROWS: XOR BH,BH
MOV DL,24
MOV AX,1130H
INT 10H
MOV ROWS,DL ;Store rows.
SUB DL,MENU_LINES - 1
XOR DH,DH
MOV LISTING_LEN,DX
POP ES
MOV DI,OFFSET COLOR
MOV CX,SIZE COLOR_ATTRIBS
REP MOVSB
;----------------------------------------------;
DISPLAY_SETUP: CALL CLS ;Clear screen.
CMP BORDER_FLAG,1
JZ DO_COPYRIGHT
MOV BL,COLOR.W ;Turn on border.
AND BL,7
XOR BH,BH
MOV AH,0BH
INT 10H
DO_COPYRIGHT: XOR AX,AX
CALL CALC_ADDR
INC DI
INC DI
MOV SI,OFFSET COPYRIGHT ;Point to copyright message.
MOV BH,COLOR.B ;Use header attribute.
CALL WRITE_STRING ;And display it.
RET
;----------------------------------------------;
; INPUT: SI-> menu.
DISPLAY_MENU: CALL MENU_OFFSET
MOV BH,COLOR.B
CALL WRITE_STRING
RET
;*************LINE EDITOR**********************;
LINE_START DW ?
LINE_END DW ?
SCREEN_START DW ?
;INPUT: BH=color; LINE_START=buffer position; LINE_END; SCREEN_START.
;OUTPUT: CY=1 if Esc pressed.
EDITOR: MOV DI,LINE_START
CALL EDIT_CURSOR
CALL DISP_EDIT
EDITOR2: CALL CK_KEY
JZ EDITOR2
OR AL,AL
JZ NEXT_EDIT
CMP AL,CR
JZ NEXT_EDIT
CMP AH,ESC_SCAN
JZ NEXT_EDIT
MOV CX,LINE_END
SUB CX,LINE_START
PUSH DI
MOV AL,SPACE
REP STOSB
POP DI
NEXT_EDIT: CALL EDIT_CURSOR
CALL DISP_EDIT
CALL GETKEY
XCHG AL,AH
NEXT_EDIT2: JNC DO_EDIT
JMP EDITOR_END
DO_EDIT: MOV DX,LINE_START
MOV CX,LINE_END
CMP AH,ENTER_SCAN
JNZ CK_RIGHT
JMP EDITOR_DONE
CK_RIGHT: CMP AX,RIGHT_SCAN SHL 8
JNZ CK_LEFT
CMP DI,CX
JZ NEXT_EDIT
INC DI
CK_LEFT: CMP AX,LEFT_SCAN SHL 8
JNZ CK_BS
CMP DI,DX
JZ NEXT_EDIT
DEC DI
JMP NEXT_EDIT
CK_BS: CMP AH,BS_SCAN
JNZ CK_DEL
CMP DI,DX
JZ NEXT_EDIT
DEC DI
CALL CK_INSERT
JNZ DO_DEL1
MOV BYTE PTR [DI],SPACE
JMP NEXT_EDIT
CK_DEL: CMP AX,DEL_SCAN SHL 8
JNZ CK_HOME
DO_DEL1: CALL DO_DEL
JMP NEXT_EDIT
CK_HOME: CMP AX,HOME_SCAN SHL 8
JNZ CK_END2
MOV DI,DX
CK_END2: CMP AX,END_SCAN SHL 8
JNZ CK_ASCII
MOV DI,CX
NEXT_CK_END2: CMP DI,DX
JZ NEXT_EDIT
CMP BYTE PTR [DI-1],SPACE
JNZ NEXT_EDIT
DEC DI
JMP NEXT_CK_END2
CK_ASCII: CALL CK_LEGAL
JC NEXT_EDIT
CMP DI,CX
JAE NEXT_EDIT
CALL CK_INSERT
JNZ DO_INSERT
STOSB
JMP NEXT_EDIT
DO_INSERT: MOV DX,DI
DEC CX
MOV DI,CX
SUB CX,DX
JZ DO_INSERT2
MOV SI,DI
DEC SI
STD
REP MOVSB
CLD
DO_INSERT2: MOV DI,DX
STOSB
JMP NEXT_EDIT
EDITOR_DONE: CLC
EDITOR_END: PUSHF
CALL HIDE_CURSOR
POPF
RET
;--------------;
LEGAL_CHARS DW ?
NUMBERS DB "1234567890abcdefhABCDEFH"
NUMBERS_LEN EQU $ - NUMBERS
CK_LEGAL: CMP AL,SPACE
JB ILLEGAL
CMP AL,127
JA ILLEGAL
JMP [LEGAL_CHARS]
NUMBER_CHARS: PUSH DI
PUSH CX
MOV DI,OFFSET NUMBERS
MOV CX,NUMBERS_LEN
REPNZ SCASB
POP CX
POP DI
JNZ ILLEGAL
ALL_CHARS: CLC
RET
ILLEGAL: STC
RET
;--------------------------
DO_DEL: PUSH DI
MOV SI,DI
INC SI
DEC CX
SUB CX,DI
JS DEL_END
REP MOVSB
MOV BYTE PTR [DI],SPACE
DEL_END: POP DI
RET
;--------------------------
CK_INSERT: PUSH DS
MOV DX,40H
MOV DS,DX
MOV DL,DS:[17H]
TEST DL,80H ;Insert
POP DS
RET
;--------------------------
EDIT_CURSOR: MOV AX,SCREEN_START
XOR DX,DX
DIV CRT_WIDTH
SHR DL,1
MOV DH,AL
MOV AX,DI
SUB AX,LINE_START
ADD DL,AL
CALL SET_CURSOR
RET
;--------------------------
DISP_EDIT: PUSH DI
MOV DI,SCREEN_START
MOV SI,LINE_START
CALL WRITE_STRING
POP DI
RET
;----------------------------------------------;
;INPUT: CX=char count; AX=character
REPEAT_CHAR: PUSH AX
CALL WRITE_SCREEN
POP AX
LOOP REPEAT_CHAR
RET
;----------------------------------------------;
; INPUT: AX = Starting line; OUTPUT: DI = Video address.
CALC_ADDR: MUL CRT_WIDTH
ADD AX,CRT_START
MOV DI,AX
RET
;----------------------------------------------;
; INPUT: AL = character to write; BH = attribute.
WRITE_SCREEN: PUSH ES
MOV ES,CS:VIDEO_SEG ;Point to screen segment.
MOV DX,CS:STATUS_REG ;Retrieve status register.
MOV BL,AL ;Store character in BL.
HORZ_RET: IN AL,DX ;Get status.
RCR AL,1 ;Is it low?
JC HORZ_RET ;If not, wait until it is.
CLI ;No more interrupts.
HWAIT: IN AL,DX ;Get status.
RCR AL,1 ;Is it high?
JNC HWAIT ;If no, wait until it is.
MOV AX,BX ;Retrieve character; now it's OK
STOSW ; to write to screen buffer.
STI ;Interrupts back on.
POP ES
RET ;Return
;----------------------------------------------;
; INPUT: AL=character to write; BH=attribute.
WRITE_CHAR: PUSH ES
MOV DX,CS:STATUS_REG
MOV ES,CS:VIDEO_SEG
MOV BL,AL ;Store character in BL.
HORZ_RET2: IN AL,DX ;Get status.
RCR AL,1 ;Is it low?
JC HORZ_RET2 ;If not, wait until it is.
CLI ;No more interrupts.
HWAIT2: IN AL,DX ;Get status.
RCR AL,1 ;Is it high?
JNC HWAIT2 ;If no, wait until it is.
MOV AX,BX ;Retrieve character; now it's OK
STOSW ; to write to screen buffer.
STI ;Interrupts back on.
POP ES
RET ;Return
;----------------------------------------------;
; INPUT: SI -> to string to display; DI -> where to display it.
; Entry point is WRITE_STRING.
WRITE_IT: CALL WRITE_SCREEN ;Write a character.
WRITE_STRING: LODSB ;Retrieve a character.
CMP AL,CR ;Keep writing until a carriage
JA WRITE_IT ; return or zero encountered.
RET
;----------------------------------------------;
CLEAR_MENU: CALL MENU_OFFSET ;Calculate menu screen offset.
PUSH DI
MOV BH,COLOR.B ;Menu attribute.
MOV CX,CRT_WIDTH ;Blank out the two lines of menu.
SHR CX,1
NEXT_MENU: MOV AL,SPACE
CALL WRITE_SCREEN
LOOP NEXT_MENU
POP DI
RET
;----------------------------------------;
; OUTPUT: DI -> Screen offset for menu. ;
;----------------------------------------;
MENU_OFFSET: MOV AL,ROWS
XOR AH,AH
CALL CALC_ADDR
RET
;----------------------------------------------;
CLS: MOV BH,COLOR.B ;Normal attribute.
CLS2: XOR CX,CX ;Top left corner.
MOV DL,BYTE PTR COLUMNS
DEC DL
MOV DH,ROWS
MOV AX,600H ;Scroll active page.
PUSH BP
INT 10H
POP BP
RET
;----------------------------------------------;
CLOSE_SCREEN: PUSH AX
MOV BH,SCREEN_COLOR
CALL CLS2
CMP BORDER_FLAG,1
JZ PLACE_CURSOR
XOR BX,BX
MOV AH,0BH
INT 10H
PLACE_CURSOR: XOR DX,DX
CALL SET_CURSOR
POP AX
RET
;----------------------------------------------;
BEEP: MOV BX,NOTE ;Tone frequency divisor.
MOV DX,12H
XOR AX,AX
DIV BX
MOV BX,AX ;8253 countdown.
CALL DELAY ;Wait till clock rolls over.
MOV AL,0B6H ;Channel 2 speaker functions.
OUT 43H,AL ;8253 Mode Control.
JMP $+2 ;IO delay.
MOV AX,BX ;Retrieve countdown.
OUT 42H,AL ;Channel 2 LSB.
JMP $+2
MOV AL,AH ;Channel 2 MSB.
OUT 42H,AL
IN AL,61H ;Port B.
OR AL,3 ;Turn on speaker.
JMP $+2
OUT 61H,AL
CALL DELAY ;Delay one second.
IN AL,61H ;Get Port B again.
AND AL,NOT 3 ;Turn speaker off.
JMP $+2
OUT 61H,AL
RET ;Done.
;-----------------------------;
DELAY: PUSH DS ;Preserve data segment.
MOV AX,40H ;Point to BIOS data segment.
MOV DS,AX
MOV AX,DS:[6CH] ;Retrieve timer low.
NEXT_BEEP: MOV DX,DS:[6CH] ;Retrieve timer low.
CMP DX,AX ;Have we timed out?
JZ NEXT_BEEP ;If not, wait until second up.
POP DS ;Restore data segment.
RET
;----------------------------------------------;
; INPUT: SI-> DIR storage.
GET_DIR: MOV BYTE PTR [SI],"\" ;DOS doesn't preface directory
INC SI ; with slash so we must.
XOR DL,DL
MOV AH,47H ;Get current directory.
INT 21H
RET
;----------------------------------------------;
HIDE_CURSOR: MOV DH,ROWS ;Retrieve CRT rows.
INC DH ;Move one line below off screen.
XOR DL,DL ;Column zero.
SET_CURSOR: PUSH BX
XOR BH,BH ;Page zero.
MOV AH,2 ;Set cursor position.
INT 10H
POP BX
RET
;----------------------------------------------;
RESTORE_DIR: MOV DX,OFFSET CURRENT_DIR
CALL CHANGE_DIR
MOV DL,DEFAULT_DRIVE
CALL SELECT_DISK
RET
;----------------------------------------------;
SELECT_DISK: MOV AH,0EH
INT 21H
RET
;----------------------------------------------;
CHANGE_DIR: MOV AH,3BH ;Change current directory.
INT 21H
RET
;----------------------------------------------;
SET_ZIF: CALL RESTORE_DIR
MOV DL,ZIF_DRIVE
CALL SELECT_DISK
MOV SI,OFFSET CURRENT_DIR
CALL GET_DIR
MOV DX,OFFSET ZIF_DIR
CALL CHANGE_DIR
RET
;----------------------------------------------;
SET_PGM: CALL RESTORE_DIR
MOV DL,PGM_DRIVE
CALL SELECT_DISK
MOV SI,OFFSET CURRENT_DIR
CALL GET_DIR
MOV DX,OFFSET PGM_DIR
CALL CHANGE_DIR
RET
;----------------------------------------------;
; INPUT: AL=Scan code; AH=Char; DI -> Valid scan codes table; CX = Table length
; OUTPUT: AL=Scan code; AH=Char.
DISPATCH: PUSH AX
MOV BX,CX
MOV DX,DI
ADD DX,CX
REPNZ SCASB
JNZ DISPATCH_END
GOT_DISPATCH: SUB BX,CX
DEC BX
SHL BX,1
ADD BX,DX
CALL GET_PARAMS
CALL [BX] ;Process the command.
DISPATCH_END: POP AX
RET
;----------------------------------------------;
GET_PARAMS: MOV AX,SIZE FILE_RECORD
MUL LISTING_LEN
MOV BP,BAR_ADDR
MOV DX,LISTING_ADDR
MOV CX,LAST_ADDR
PARAMS_END: RET
;----------------------------------------------;
GETKEY: TEST KBD_STATUS,80H
JNZ KEY_CLEAR
CALL CK_KEY
JNZ GETKEY2
JMP GETKEY
KEY_CLEAR: CALL CK_KEY
JNZ GETKEY2
MOV KBD_STATUS,0
CMP FILE_CURRENT,TRUE
JZ GETKEY
CALL DISP_FILE
JMP GETKEY
GETKEY2: XOR AH,AH ;Wait for next keyboard input.
INT 16H
XCHG AH,AL
CMP AL,ESC_SCAN
STC
JZ GETKEY_END
CLC
GETKEY_END: RET
CK_KEY: MOV AH,1 ;Is there a keystroke available.
INT 16H
RET
CLEAR_IT: XOR AH,AH
INT 16H ;Read keystrokes until buffer
CLEAR_KEY: CALL CK_KEY ; empty.
JNZ CLEAR_IT
RET
;----------------------------------------------;
WRITE_TTY: MOV AH,0EH
INT 10H
RET
;----------------------------------------------;
PRINT_STRING: MOV AH,9 ;Print string via DOS.
INT 21H
RET
;----------------------------------------------;
OLD9 DW ?,?
INSTALL_9: PUSH ES
MOV AX,3509H ;INT 9
INT 21H
MOV OLD9[0],BX
MOV OLD9[2],ES
MOV DX,OFFSET INT_9 ;Install new interrupt.
MOV AX,2509H
INT 21H
POP ES
RET
;----------------------------------------------;
UNINSTALL_9: PUSH DS
MOV DX,OLD9[0] ;Restore old INT 9.
MOV DS,OLD9[2]
MOV AX,2509H
INT 21H
POP DS
RET
;----------------------------------------------;
INSTALL_24: MOV DX,OFFSET INT_24 ;Install new interrupt.
MOV AX,2524H
INT 21H
RET
EVEN
STACK_POINTER = $ + 256
_TEXT ENDS
END START